diff options
Diffstat (limited to 'doc')
113 files changed, 7490 insertions, 14599 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am index c5fd2b81a14..de68c20b4d7 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,13 +1,9 @@ -EXTRA_DIST = glusterfs.vol.sample glusterfsd.vol.sample glusterfs.8 mount.glusterfs.8\ - porting_guide.txt authentication.txt coding-standard.pdf get_put_api_using_xattr.txt \ - translator-options.txt mac-related-xattrs.txt replicate.pdf glusterd.vol gluster.8 \ - glusterd.8 glusterfsd.8 +EXTRA_DIST = glusterfs.8 mount.glusterfs.8 gluster.8 \ + glusterd.8 glusterfsd.8 -SUBDIRS = examples hacker-guide +man8_MANS = glusterfs.8 mount.glusterfs.8 gluster.8 +if WITH_SERVER +man8_MANS += glusterd.8 glusterfsd.8 +endif -voldir = $(sysconfdir)/glusterfs -vol_DATA = glusterfs.vol.sample glusterfsd.vol.sample glusterd.vol - -man8_MANS = glusterfs.8 mount.glusterfs.8 gluster.8 glusterd.8 glusterfsd.8 - -CLEANFILES = +CLEANFILES = diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000000..6aa28642ef4 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,26 @@ +## Developer Guide + +Gluster's contributors can check about the internals by visiting [Developer Guide Section](developer-guide). While it is not 'comprehensive', it can help you to get started. + +Also while coding, keep [Coding Standard](developer-guide/coding-standard.md) in mind. + +When you are ready to commit the changes, make sure you meet our [Commit message standard](developer-guide/commit-guidelines.md). + +## Admin Guide ## + +The gluster administration guide is maintained at [github](https://github.com/gluster/glusterdocs). The browsable admin guide can be found [here](http://docs.gluster.org/en/latest/Administrator%20Guide/). + +The doc patch has to be sent against the above mentioned repository. + +## Features/Spec ## + +The Gluster features which are 'in progress' or implemented can be found at [github](https://github.com/gluster/glusterfs-specs). + +## Upgrade Guide ## + +The gluster upgrade guide is maintained at [github](https://github.com/gluster/glusterdocs). The browsable upgrade guide can be found [here](http://docs.gluster.org/en/latest/Upgrade-Guide) + +The doc patch has to be sent against the above mentioned repository. + + +For more details about the docuemntation workflow please refer [this discussion](https://www.mail-archive.com/gluster-users@gluster.org/msg21168.html) diff --git a/doc/authentication.txt b/doc/authentication.txt deleted file mode 100644 index 70aafd93334..00000000000 --- a/doc/authentication.txt +++ /dev/null @@ -1,112 +0,0 @@ - -* Authentication is provided by two modules addr and login. Login based authentication uses username/password from client for authentication. Each module returns either ACCEPT, REJCET or DONT_CARE. DONT_CARE is returned if the input authentication information to the module is not concerned to its working. The theory behind authentication is that "none of the auth modules should return REJECT and atleast one of them should return ACCEPT" - -* Currently all the authentication related information is passed un-encrypted over the network from client to server. - ----------------------------------------------------------------------------------------------------- -* options provided in protocol/client: - * for username/password based authentication: - option username <username> - option password <password> - * client can have only one set of username/password - * for addr based authentication: - * no options required in protocol/client. Client has to bind to privileged port (port < 1024 ) which means the process in which protocol/client is loaded has to be run as root. - ----------------------------------------------------------------------------------------------------- -* options provided in protocol/server: - * for username/password based authentication: - option auth.login.<brick>.allow [comma seperated list of usernames using which clients can connect to volume <brick>] - option auth.login.<username>.password <password> #specify password <password> for username <username> - * for addr based authentication: - option auth.addr.<brick>.allow [comma seperated list of ip-addresses/unix-paths from which clients are allowed to connect to volume <brick>] - option auth.addr.<brick>.reject [comma seperated list of ip-addresses/unix-paths from which clients are not allowed to connect to volume <brick>] - * negation operator '!' is used to invert the sense of matching. - Eg., option auth.addr.brick.allow !a.b.c.d #do not allow client from a.b.c.d to connect to volume brick - option auth.addr.brick.reject !w.x.y.z #allow client from w.x.y.z to connect to volume brick - * wildcard '*' can be used to match any ip-address/unix-path - ----------------------------------------------------------------------------------------------------- - -* Usecases: - -* username/password based authentication only - protocol/client: - option username foo - option password foo-password - option remote-subvolume foo-brick - - protocol/server: - option auth.login.foo-brick.allow foo,who #,other users allowed to connect to foo-brick - option auth.login.foo.password foo-password - option auth.login.who.password who-password - - * in protocol/server, dont specify ip from which client is connecting in auth.addr.foo-brick.reject list - -**************************************************************************************************** - -* ip based authentication only - protocol/client: - option remote-subvolume foo-brick - * Client is connecting from a.b.c.d - - protocol/server: - option auth.addr.foo-brick.allow a.b.c.d,e.f.g.h,i.j.k.l #, other ip addresses from which clients are allowed to connect to foo-brick - -**************************************************************************************************** -* ip and username/password based authentication - * allow only "user foo from a.b.c.d" - protocol/client: - option username foo - option password foo-password - option remote-subvolume foo-brick - - protocol/server: - option auth.login.foo-brick.allow foo - option auth.login.foo.password foo-password - option auth.addr.foo-brick.reject !a.b.c.d - - * allow only "user foo" from a.b.c.d i.e., only user foo is allowed from a.b.c.d, but anyone is allowed from ip addresses other than a.b.c.d - protocol/client: - option username foo - option password foo-password - option remote-subvolume foo-brick - - protocol/server: - option auth.login.foo-brick.allow foo - option auth.login.foo.password foo-password - option auth.addr.foo-brick.allow !a.b.c.d - - * reject only "user shoo from a.b.c.d" - protcol/client: - option remote-subvolume shoo-brick - - protocol/server: - # observe that no "option auth.login.shoo-brick.allow shoo" given - # Also other users from a.b.c.d have to be explicitly allowed using auth.login.shoo-brick.allow ... - option auth.addr.shoo-brick.allow !a.b.c.d - - * reject only "user shoo" from a.b.c.d i.e., user shoo from a.b.c.d has to be rejected. - * same as reject only "user shoo from a.b.c.d" above, but rules have to be added whether to allow ip addresses (and users from those ips) other than a.b.c.d - -**************************************************************************************************** - -* ip or username/password based authentication - - * allow user foo or clients from a.b.c.d - protocol/client: - option remote-subvolume foo-brick - - protocol/server: - option auth.login.foo-brick.allow foo - option auth.login.foo.password foo-password - option auth.addr.foo-brick.allow a.b.c.d - - * reject user shoo or clients from a.b.c.d - protocol/client: - option remote-subvolume shoo-brick - - protocol/server: - option auth.login.shoo-brick.allow <usernames other than shoo> - #for each username mentioned in the above <usernames other than shoo> list, specify password as below - option auth.login.<username other than shoo>.password password - option auth.addr.shoo-brick.reject a.b.c.d diff --git a/doc/booster.txt b/doc/booster.txt deleted file mode 100644 index 684ac8965c4..00000000000 --- a/doc/booster.txt +++ /dev/null @@ -1,54 +0,0 @@ -Introduction -============ -* booster is a LD_PRELOADable library which boosts read/write performance by bypassing fuse for - read() and write() calls. - -Requirements -============ -* fetch volfile from glusterfs. -* identify whether multiple files are from the same mount point. If so, use only one context. - -Design -====== -* for a getxattr, along with other attributes, fuse returns following attributes. - * contents of client volume-file. - * mount point. - -* LD_PRELOADed booster.so maintains an hash table storing mount-points and libglusterfsclient handles - so that handles are reused for files from same mount point. - -* it also maintains a fdtable. fdtable maps the fd (integer) returned to application to fd (pointer to fd struct) - used by libglusterfsclient. application is returned the same fd as the one returned from libc apis. - -* During fork, these tables are overwritten to enable creation of fresh glusterfs context in child. - -Working -======= -* application willing to use booster LD_PRELOADs booster.so which is a wrapper library implementing - open, read and write. - -* application should specify the path to logfile through the environment variable GLFS_BOOSTER_LOGFILE. If - not specified, logging is done to /dev/stderr. - -* open call does, - * real_open on the file. - * fgetxattr(fd). - * store the volume-file content got in the dictionary to a temparory file. - * look in the hashtable for the mount-point, if already present get the libglusterfsclient handle from the - hashtable. Otherwise get a new handle from libglusterfsclient (be careful about mount point not present in - the hashtable and multiple glusterfs_inits running simultaneously for the same mount-point there by using - multiple handles for the same mount point). - * real_close (fd). - * delete temporary volume-volfile. - * glusterfs_open (handle, path, mode). - * store the fd returned by glusterfs_open in the fdtable at the same index as the fd returned by real_open. - * return the index as fd. - -* read/write calls do, - * get the libglusterfsclient fd from fdtable. - * if found use glusterfs_read/glusterfs_write, else use real_read/real_write. - -* close call does, - * remove the fd from the fdtable. - -* other calls use real_calls. diff --git a/doc/coding-standard.pdf b/doc/coding-standard.pdf Binary files differdeleted file mode 100644 index bc9cb56202c..00000000000 --- a/doc/coding-standard.pdf +++ /dev/null diff --git a/doc/coding-standard.tex b/doc/coding-standard.tex deleted file mode 100644 index 92f799c013f..00000000000 --- a/doc/coding-standard.tex +++ /dev/null @@ -1,385 +0,0 @@ -\documentclass{article}[12pt] -\usepackage{color} - -\begin{document} - - -\hrule -\begin{center}\textbf{\Large{GlusterFS Coding Standards}}\end{center} -\begin{center}\textbf{\large{\textcolor{red}{Z} Research}}\end{center} -\begin{center}{July 14, 2008}\end{center} -\hrule - -\vspace{8ex} - -\section*{$\bullet$ Structure definitions should have a comment per member} - -Every member in a structure definition must have a comment about its -purpose. The comment should be descriptive without being overly verbose. - -\vspace{2ex} -\textsl{Bad}: - -\begin{verbatim} - gf_lock_t lock; /* lock */ -\end{verbatim} - -\textsl{Good}: - -\begin{verbatim} - DBTYPE access_mode; /* access mode for accessing - * the databases, can be - * DB_HASH, DB_BTREE - * (option access-mode <mode>) - */ -\end{verbatim} - -\section*{$\bullet$ Declare all variables at the beginning of the function} -All local variables in a function must be declared immediately after the -opening brace. This makes it easy to keep track of memory that needs to be freed -during exit. It also helps debugging, since gdb cannot handle variables -declared inside loops or other such blocks. - -\section*{$\bullet$ Always initialize local variables} -Every local variable should be initialized to a sensible default value -at the point of its declaration. All pointers should be initialized to NULL, -and all integers should be zero or (if it makes sense) an error value. - -\vspace{2ex} - -\textsl{Good}: - -\begin{verbatim} - int ret = 0; - char *databuf = NULL; - int _fd = -1; -\end{verbatim} - -\section*{$\bullet$ Initialization should always be done with a constant value} -Never use a non-constant expression as the initialization value for a variable. - -\vspace{2ex} - -\textsl{Bad}: - -\begin{verbatim} - pid_t pid = frame->root->pid; - char *databuf = malloc (1024); -\end{verbatim} - -\section*{$\bullet$ Validate all arguments to a function} -All pointer arguments to a function must be checked for \texttt{NULL}. -A macro named \texttt{VALIDATE} (in \texttt{common-utils.h}) -takes one argument, and if it is \texttt{NULL}, writes a log message and -jumps to a label called \texttt{err} after setting op\_ret and op\_errno -appropriately. It is recommended to use this template. - -\vspace{2ex} - -\textsl{Good}: - -\begin{verbatim} - VALIDATE(frame); - VALIDATE(this); - VALIDATE(inode); -\end{verbatim} - -\section*{$\bullet$ Never rely on precedence of operators} -Never write code that relies on the precedence of operators to execute -correctly. Such code can be hard to read and someone else might not -know the precedence of operators as accurately as you do. -\vspace{2ex} - -\textsl{Bad}: - -\begin{verbatim} - if (op_ret == -1 && errno != ENOENT) -\end{verbatim} - -\textsl{Good}: - -\begin{verbatim} - if ((op_ret == -1) && (errno != ENOENT)) -\end{verbatim} - -\section*{$\bullet$ Use exactly matching types} -Use a variable of the exact type declared in the manual to hold the -return value of a function. Do not use an ``equivalent'' type. - -\vspace{2ex} - -\textsl{Bad}: - -\begin{verbatim} - int len = strlen (path); -\end{verbatim} - -\textsl{Good}: - -\begin{verbatim} - size_t len = strlen (path); -\end{verbatim} - -\section*{$\bullet$ Never write code such as \texttt{foo->bar->baz}; check every pointer} -Do not write code that blindly follows a chain of pointer -references. Any pointer in the chain may be \texttt{NULL} and thus -cause a crash. Verify that each pointer is non-null before following -it. - -\section*{$\bullet$ Check return value of all functions and system calls} -The return value of all system calls and API functions must be checked -for success or failure. - -\vspace{2ex} -\textsl{Bad}: - -\begin{verbatim} - close (fd); -\end{verbatim} - -\textsl{Good}: - -\begin{verbatim} - op_ret = close (_fd); - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "close on file %s failed (%s)", real_path, - strerror (errno)); - op_errno = errno; - goto out; - } -\end{verbatim} - - -\section*{$\bullet$ Gracefully handle failure of malloc} -GlusterFS should never crash or exit due to lack of memory. If a -memory allocation fails, the call should be unwound and an error -returned to the user. - -\section*{$\bullet$ Use result args and reserve the return value to indicate success or failure} -The return value of every functions must indicate success or failure (unless -it is impossible for the function to fail --- e.g., boolean functions). If -the function needs to return additional data, it must be returned using a -result (pointer) argument. - -\vspace{2ex} -\textsl{Bad}: - -\begin{verbatim} - int32_t dict_get_int32 (dict_t *this, char *key); -\end{verbatim} - -\textsl{Good}: - -\begin{verbatim} - int dict_get_int32 (dict_t *this, char *key, int32_t *val); -\end{verbatim} - -\section*{$\bullet$ Always use the `n' versions of string functions} -Unless impossible, use the length-limited versions of the string functions. - -\vspace{2ex} -\textsl{Bad}: - -\begin{verbatim} - strcpy (entry_path, real_path); -\end{verbatim} - -\textsl{Good}: - -\begin{verbatim} - strncpy (entry_path, real_path, entry_path_len); -\end{verbatim} - -\section*{$\bullet$ No dead or commented code} -There must be no dead code (code to which control can never be passed) or -commented out code in the codebase. - -\section*{$\bullet$ Only one unwind and return per function} -There must be only one exit out of a function. \texttt{UNWIND} and return -should happen at only point in the function. - -\section*{$\bullet$ Function length or Keep functions small} -We live in the UNIX-world where modules do one thing and do it well. -This rule should apply to our functions also. If a function is very long, try splitting it -into many little helper functions. The question is, in a coding -spree, how do we know a function is long and unreadable. One rule of -thumb given by Linus Torvalds is that, a function should be broken-up -if you have 4 or more levels of indentation going on for more than 3-4 -lines. - -\vspace{2ex} -\textsl{Example for a helper function}: -\begin{verbatim} - static int - same_owner (posix_lock_t *l1, posix_lock_t *l2) - { - return ((l1->client_pid == l2->client_pid) && - (l1->transport == l2->transport)); - } -\end{verbatim} - -\section*{$\bullet$ Defining functions as static} -Define internal functions as static only if you're -very sure that there will not be a crash(..of any kind..) emanating in -that function. If there is even a remote possibility, perhaps due to -pointer derefering, etc, declare the function as non-static. This -ensures that when a crash does happen, the function name shows up the -in the back-trace generated by libc. However, doing so has potential -for polluting the function namespace, so to avoid conflicts with other -components in other parts, ensure that the function names are -prepended with a prefix that identify the component to which it -belongs. For eg. non-static functions in io-threads translator start -with iot\_. - -\section*{$\bullet$ Ensure function calls wrap around after -80-columns.} -Place remaining arguments on the next line if needed. - -\section*{$\bullet$ Functions arguments and function definition} -Place all the arguments of a function definition on the same line -until the line goes beyond 80-cols. Arguments that extend beyind -80-cols should be placed on the next line. - -\section*{Style issues} - -\subsection*{Brace placement} -Use K\&R/Linux style of brace placement for blocks. - -\textsl{Example}: -\begin{verbatim} - int some_function (...) - { - if (...) { - /* ... */ - } else if (...) { - /* ... */ - } else { - /* ... */ - } - - do { - /* ... */ - } while (cond); - } -\end{verbatim} - -\subsection*{Indentation} -Use \textbf{eight} spaces for indenting blocks. Ensure that your -file contains only spaces and not tab characters. You can do this -in Emacs by selecting the entire file (\texttt{C-x h}) and -running \texttt{M-x untabify}. - -To make Emacs indent lines automatically by eight spaces, add this -line to your \texttt{.emacs}: - -\begin{verbatim} - (add-hook 'c-mode-hook (lambda () (c-set-style "linux"))) -\end{verbatim} - -\subsection*{Comments} -Write a comment before every function describing its purpose (one-line), -its arguments, and its return value. Mention whether it is an internal -function or an exported function. - -Write a comment before every structure describing its purpose, and -write comments about each of its members. - -Follow the style shown below for comments, since such comments -can then be automatically extracted by doxygen to generate -documentation. - -\textsl{Example}: -\begin{verbatim} -/** - * hash_name -hash function for filenames - * @par: parent inode number - * @name: basename of inode - * @mod: number of buckets in the hashtable - * - * @return: success: bucket number - * failure: -1 - * - * Not for external use. - */ -\end{verbatim} - -\subsection*{Indicating critical sections} -To clearly show regions of code which execute with locks held, use -the following format: - -\begin{verbatim} - pthread_mutex_lock (&mutex); - { - /* code */ - } - pthread_mutex_unlock (&mutex); -\end{verbatim} - -\section*{A skeleton fop function} -This is the recommended template for any fop. In the beginning come -the initializations. After that, the `success' control flow should be -linear. Any error conditions should cause a \texttt{goto} to a single -point, \texttt{out}. At that point, the code should detect the error -that has occured and do appropriate cleanup. - -\begin{verbatim} -int32_t -sample_fop (call_frame_t *frame, xlator_t *this, ...) -{ - char * var1 = NULL; - int32_t op_ret = -1; - int32_t op_errno = 0; - DIR * dir = NULL; - struct posix_fd * pfd = NULL; - - VALIDATE_OR_GOTO (frame, out); - VALIDATE_OR_GOTO (this, out); - - /* other validations */ - - dir = opendir (...); - - if (dir == NULL) { - op_errno = errno; - gf_log (this->name, GF_LOG_ERROR, - "opendir failed on %s (%s)", loc->path, - strerror (op_errno)); - goto out; - } - - /* another system call */ - if (...) { - op_errno = ENOMEM; - gf_log (this->name, GF_LOG_ERROR, - "out of memory :("); - goto out; - } - - /* ... */ - - out: - if (op_ret == -1) { - - /* check for all the cleanup that needs to be - done */ - - if (dir) { - closedir (dir); - dir = NULL; - } - - if (pfd) { - if (pfd->path) - FREE (pfd->path); - FREE (pfd); - pfd = NULL; - } - } - - STACK_UNWIND (frame, op_ret, op_errno, fd); - return 0; -} -\end{verbatim} - -\end{document} diff --git a/doc/debugging/analyzing-regression-cores.md b/doc/debugging/analyzing-regression-cores.md new file mode 100644 index 00000000000..5e10f41c6eb --- /dev/null +++ b/doc/debugging/analyzing-regression-cores.md @@ -0,0 +1,54 @@ +# Analyzing Regression Cores +This document explains how to analyze core-dumps obtained from regression machines, with examples. +1. Download the core-tarball and extract it. +2. `cd` into directory where the tarball is extracted. +``` +[sh]# pwd +/home/user/Downloads +[sh]# ls +build build-install-20150625_05_42_39.tar.bz2 lib64 usr +``` +3. Determine the core file you need to examine. There can be more than one core file. You can list them from './build/install/cores' directory. +``` +[sh]# ls build/install/cores/ +core.9341 liblist.txt liblist.txt.tmp +``` +In case you are unsure which binary generated the core-file, executing 'file' command on it will help. +``` +[sh]# file ./build/install/cores/core.9341 +./build/install/cores/core.9341: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from '/build/install/sbin/glusterfsd -s slave26.cloud.gluster.org --volfile-id patchy' +``` +As seen, the core file was generated by glusterfsd binary, and path to it is provided (/build/install/sbin/glusterfsd). + +4. Now, run the following command on the core: +``` +gdb -ex 'set sysroot ./' -ex 'core-file ./build/install/cores/core.xxx' <target, say ./build/install/sbin/glusterd> +In this case, +gdb -ex 'set sysroot ./' -ex 'core-file ./build/install/cores/core.9341' ./build/install/sbin/glusterfsd +``` +5. You can cross check if all shared libraries are available and loaded by using 'info sharedlibrary' command from inside gdb. +6. Once verified, usual gdb commands based on requirement can be used to debug the core. + `bt` or `backtrace` from gdb of core used in examples: +``` +Core was generated by `/build/install/sbin/glusterfsd -s slave26.cloud.gluster.org --volfile-id patchy'. +Program terminated with signal SIGABRT, Aborted. +#0 0x00007f512a54e625 in raise () from ./lib64/libc.so.6 +(gdb) bt +#0 0x00007f512a54e625 in raise () from ./lib64/libc.so.6 +#1 0x00007f512a54fe05 in abort () from ./lib64/libc.so.6 +#2 0x00007f512a54774e in __assert_fail_base () from ./lib64/libc.so.6 +#3 0x00007f512a547810 in __assert_fail () from ./lib64/libc.so.6 +#4 0x00007f512b9fc434 in __gf_free (free_ptr=0x7f50f4000e50) at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/libglusterfs/src/mem-pool.c:304 +#5 0x00007f512b9b6657 in loc_wipe (loc=0x7f510c20d1a0) at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/libglusterfs/src/xlator.c:685 +#6 0x00007f511cb8201d in mq_start_quota_txn_v2 (this=0x7f5118019b60, loc=0x7f510c20d2b8, ctx=0x7f50f4000bf0, contri=0x7f50f4000d60) + at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/xlators/features/marker/src/marker-quota.c:2921 +#7 0x00007f511cb82c55 in mq_initiate_quota_task (opaque=0x7f510c20d2b0) at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/xlators/features/marker/src/marker-quota.c:3199 +#8 0x00007f511cb81820 in mq_synctask (this=0x7f5118019b60, task=0x7f511cb829fa <mq_initiate_quota_task>, spawn=_gf_false, loc=0x7f510c20d430, dict=0x0, buf=0x0, contri=0) + at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/xlators/features/marker/src/marker-quota.c:2789 +#9 0x00007f511cb82f82 in mq_initiate_quota_blocking_txn (this=0x7f5118019b60, loc=0x7f510c20d430) at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/xlators/features/marker/src/marker-quota.c:3230 +#10 0x00007f511cb82844 in mq_reduce_parent_size_task (opaque=0x7f510c000df0) at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/xlators/features/marker/src/marker-quota.c:3117 +#11 0x00007f512ba0f9dc in synctask_wrap (old_task=0x7f510c0053e0) at /home/jenkins/root/workspace/rackspace-regression-2GB-triggered/libglusterfs/src/syncop.c:370 +#12 0x00007f512a55f8f0 in ?? () from ./lib64/libc.so.6 +#13 0x0000000000000000 in ?? () +(gdb) +``` diff --git a/doc/debugging/gfid-to-path.md b/doc/debugging/gfid-to-path.md new file mode 100644 index 00000000000..1917bf2cca1 --- /dev/null +++ b/doc/debugging/gfid-to-path.md @@ -0,0 +1,68 @@ +# Convert GFID to Path + +GlusterFS internal file identifier (GFID) is a uuid that is unique to each +file across the entire cluster. This is analogous to inode number in a +normal filesystem. The GFID of a file is stored in its xattr named +`trusted.gfid`. + +#### Special mount using [gfid-access translator][1]: +``` +mount -t glusterfs -o aux-gfid-mount vm1:test /mnt/testvol +``` + +Assuming, you have `GFID` of a file from changelog (or somewhere else). +For trying this out, you can get `GFID` of a file from mountpoint: +``` +getfattr -n glusterfs.gfid.string /mnt/testvol/dir/file +``` + + +--- +### Get file path from GFID (Method 1): +**(Lists hardlinks delimited by `:`, returns path as seen from mountpoint)** + +#### Turn on build-pgfid option +``` +gluster volume set test build-pgfid on +``` +Read virtual xattr `glusterfs.ancestry.path` which contains the file path +``` +getfattr -n glusterfs.ancestry.path -e text /mnt/testvol/.gfid/<GFID> +``` + +**Example:** +``` +[root@vm1 glusterfs]# ls -il /mnt/testvol/dir/ +total 1 +10610563327990022372 -rw-r--r--. 2 root root 3 Jul 17 18:05 file +10610563327990022372 -rw-r--r--. 2 root root 3 Jul 17 18:05 file3 + +[root@vm1 glusterfs]# getfattr -n glusterfs.gfid.string /mnt/testvol/dir/file +getfattr: Removing leading '/' from absolute path names +# file: mnt/testvol/dir/file +glusterfs.gfid.string="11118443-1894-4273-9340-4b212fa1c0e4" + +[root@vm1 glusterfs]# getfattr -n glusterfs.ancestry.path -e text /mnt/testvol/.gfid/11118443-1894-4273-9340-4b212fa1c0e4 +getfattr: Removing leading '/' from absolute path names +# file: mnt/testvol/.gfid/11118443-1894-4273-9340-4b212fa1c0e4 +glusterfs.ancestry.path="/dir/file:/dir/file3" +``` + +--- +### Get file path from GFID (Method 2): +**(Does not list all hardlinks, returns backend brick path)** +``` +getfattr -n trusted.glusterfs.pathinfo -e text /mnt/testvol/.gfid/<GFID> +``` + +**Example:** +``` +[root@vm1 glusterfs]# getfattr -n trusted.glusterfs.pathinfo -e text /mnt/testvol/.gfid/11118443-1894-4273-9340-4b212fa1c0e4 +getfattr: Removing leading '/' from absolute path names +# file: mnt/testvol/.gfid/11118443-1894-4273-9340-4b212fa1c0e4 +trusted.glusterfs.pathinfo="(<DISTRIBUTE:test-dht> <POSIX(/mnt/brick-test/b):vm1:/mnt/brick-test/b/dir//file3>)" +``` + +--- +#### References and links: +[posix: placeholders for GFID to path conversion](http://review.gluster.org/5951) diff --git a/doc/debugging/mem-alloc-list.md b/doc/debugging/mem-alloc-list.md new file mode 100644 index 00000000000..1c68e65d323 --- /dev/null +++ b/doc/debugging/mem-alloc-list.md @@ -0,0 +1,19 @@ +## Viewing Memory Allocations + +While statedumps provide stats of the number of allocations, size etc for a +particular mem type, there is no easy way to examine all the allocated objects of that type +in memory.Being able to view this information could help with determining how an object is used, +and if there are any memory leaks. + +The mem_acct_rec structures have been updated to include lists to which the allocated object is +added. These can be examined in gdb using simple scripts. + +`gdb> plist xl->mem_acct.rec[$type]->obj_list` + +will print out the pointers of all allocations of $type. + +These changes are primarily targeted at developers and need to enabled +at compile-time using `configure --enable-debug`. + + + diff --git a/doc/debugging/split-brain.md b/doc/debugging/split-brain.md new file mode 100644 index 00000000000..6b122c40551 --- /dev/null +++ b/doc/debugging/split-brain.md @@ -0,0 +1,264 @@ +# Steps to recover from File split-brain +This document contains steps to recover from a file split-brain. +## Quick Start: +### Step 1. Get the path of the file that is in split-brain: +It can be obtained either by +1. The command `gluster volume heal info split-brain`. +2. Identify the files for which file operations performed from the client keep failing with Input/Output error. + +### Step 2. Close the applications that opened this file from the mount point. +In case of VMs, they need to be powered-off. + +### Step 3. Decide on the correct copy: +This is done by observing the afr changelog extended attributes of the file on +the bricks using the getfattr command; then identifying the type of split-brain +(data split-brain, metadata split-brain, entry split-brain or split-brain due to +gfid-mismatch); and finally determining which of the bricks contains the 'good copy' +of the file. +``` +getfattr -d -m . -e hex <file-path-on-brick> +``` + +It is also possible that one brick might contain the correct data while the +other might contain the correct metadata. + +### Step 4. Reset the relevant extended attribute on the brick(s) that contains the 'bad copy' of the file data/metadata using the setfattr command. +``` +setfattr -n <attribute-name> -v <attribute-value> <file-path-on-brick> +``` + +### Step 5. Trigger self-heal on the file by performing lookup from the client: +``` +ls -l <file-path-on-gluster-mount> +``` + +Detailed Instructions for steps 3 through 5: +=========================================== +To understand how to resolve split-brain we need to know how to interpret the +afr changelog extended attributes. + +Execute `getfattr -d -m . -e hex <file-path-on-brick>` + +Example: +``` +[root@store3 ~]# getfattr -d -e hex -m. brick-a/file.txt +\#file: brick-a/file.txt +security.selinux=0x726f6f743a6f626a6563745f723a66696c655f743a733000 +trusted.afr.vol-client-2=0x000000000000000000000000 +trusted.afr.vol-client-3=0x000000000200000000000000 +trusted.gfid=0x307a5c9efddd4e7c96e94fd4bcdcbd1b +``` + +The extended attributes with `trusted.afr.<volname>-client-<subvolume-index>` +are used by afr to maintain changelog of the file.The values of the +`trusted.afr.<volname>-client-<subvolume-index>` are calculated by the glusterfs +client (fuse or nfs-server) processes. When the glusterfs client modifies a file +or directory, the client contacts each brick and updates the changelog extended +attribute according to the response of the brick. + +`subvolume-index` is nothing but (brick number - 1) in +`gluster volume info <volname>` output. + +Example: +``` +[root@pranithk-laptop ~]# gluster volume info vol + Volume Name: vol + Type: Distributed-Replicate + Volume ID: 4f2d7849-fbd6-40a2-b346-d13420978a01 + Status: Created + Number of Bricks: 4 x 2 = 8 + Transport-type: tcp + Bricks: + brick-a: pranithk-laptop:/gfs/brick-a + brick-b: pranithk-laptop:/gfs/brick-b + brick-c: pranithk-laptop:/gfs/brick-c + brick-d: pranithk-laptop:/gfs/brick-d + brick-e: pranithk-laptop:/gfs/brick-e + brick-f: pranithk-laptop:/gfs/brick-f + brick-g: pranithk-laptop:/gfs/brick-g + brick-h: pranithk-laptop:/gfs/brick-h +``` + +In the example above: +``` +Brick | Replica set | Brick subvolume index +---------------------------------------------------------------------------- +-/gfs/brick-a | 0 | 0 +-/gfs/brick-b | 0 | 1 +-/gfs/brick-c | 1 | 2 +-/gfs/brick-d | 1 | 3 +-/gfs/brick-e | 2 | 4 +-/gfs/brick-f | 2 | 5 +-/gfs/brick-g | 3 | 6 +-/gfs/brick-h | 3 | 7 +``` + +Each file in a brick maintains the changelog of itself and that of the files +present in all the other bricks in it's replica set as seen by that brick. + +In the example volume given above, all files in brick-a will have 2 entries, +one for itself and the other for the file present in it's replica pair, i.e.brick-b: +``` +trusted.afr.vol-client-0=0x000000000000000000000000 -->changelog for itself (brick-a) +trusted.afr.vol-client-1=0x000000000000000000000000 -->changelog for brick-b as seen by brick-a +``` +Likewise, all files in brick-b will have: +``` +trusted.afr.vol-client-0=0x000000000000000000000000 -->changelog for brick-a as seen by brick-b +trusted.afr.vol-client-1=0x000000000000000000000000 -->changelog for itself (brick-b) +``` + +The same can be extended for other replica pairs. + +Interpreting Changelog (roughly pending operation count) Value: +Each extended attribute has a value which is 24 hexa decimal digits. +First 8 digits represent changelog of data. Second 8 digits represent changelog +of metadata. Last 8 digits represent Changelog of directory entries. + +Pictorially representing the same, we have: +``` +0x 000003d7 00000001 00000000 + | | | + | | \_ changelog of directory entries + | \_ changelog of metadata + \ _ changelog of data +``` + + +For Directories metadata and entry changelogs are valid. +For regular files data and metadata changelogs are valid. +For special files like device files etc metadata changelog is valid. +When a file split-brain happens it could be either data split-brain or +meta-data split-brain or both. When a split-brain happens the changelog of the +file would be something like this: + +Example:(Lets consider both data, metadata split-brain on same file). +``` +[root@pranithk-laptop vol]# getfattr -d -m . -e hex /gfs/brick-?/a +getfattr: Removing leading '/' from absolute path names +\#file: gfs/brick-a/a +trusted.afr.vol-client-0=0x000000000000000000000000 +trusted.afr.vol-client-1=0x000003d70000000100000000 +trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57 +\#file: gfs/brick-b/a +trusted.afr.vol-client-0=0x000003b00000000100000000 +trusted.afr.vol-client-1=0x000000000000000000000000 +trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57 +``` + +### Observations: + +#### According to changelog extended attributes on file /gfs/brick-a/a: +The first 8 digits of trusted.afr.vol-client-0 are all +zeros (0x00000000................), and the first 8 digits of +trusted.afr.vol-client-1 are not all zeros (0x000003d7................). +So the changelog on /gfs/brick-a/a implies that some data operations succeeded +on itself but failed on /gfs/brick-b/a. + +The second 8 digits of trusted.afr.vol-client-0 are +all zeros (0x........00000000........), and the second 8 digits of +trusted.afr.vol-client-1 are not all zeros (0x........00000001........). +So the changelog on /gfs/brick-a/a implies that some metadata operations succeeded +on itself but failed on /gfs/brick-b/a. + +#### According to Changelog extended attributes on file /gfs/brick-b/a: +The first 8 digits of trusted.afr.vol-client-0 are not all +zeros (0x000003b0................), and the first 8 digits of +trusted.afr.vol-client-1 are all zeros (0x00000000................). +So the changelog on /gfs/brick-b/a implies that some data operations succeeded +on itself but failed on /gfs/brick-a/a. + +The second 8 digits of trusted.afr.vol-client-0 are not +all zeros (0x........00000001........), and the second 8 digits of +trusted.afr.vol-client-1 are all zeros (0x........00000000........). +So the changelog on /gfs/brick-b/a implies that some metadata operations succeeded +on itself but failed on /gfs/brick-a/a. + +Since both the copies have data, metadata changes that are not on the other +file, it is in both data and metadata split-brain. + +Deciding on the correct copy: +----------------------------- +The user may have to inspect stat,getfattr output of the files to decide which +metadata to retain and contents of the file to decide which data to retain. +Continuing with the example above, lets say we want to retain the data +of /gfs/brick-a/a and metadata of /gfs/brick-b/a. + +Resetting the relevant changelogs to resolve the split-brain: +------------------------------------------------------------- +For resolving data-split-brain: +We need to change the changelog extended attributes on the files as if some data +operations succeeded on /gfs/brick-a/a but failed on /gfs/brick-b/a. But +/gfs/brick-b/a should NOT have any changelog which says some data operations +succeeded on /gfs/brick-b/a but failed on /gfs/brick-a/a. We need to reset the +data part of the changelog on trusted.afr.vol-client-0 of /gfs/brick-b/a. + +For resolving metadata-split-brain: +We need to change the changelog extended attributes on the files as if some +metadata operations succeeded on /gfs/brick-b/a but failed on /gfs/brick-a/a. +But /gfs/brick-a/a should NOT have any changelog which says some metadata +operations succeeded on /gfs/brick-a/a but failed on /gfs/brick-b/a. +We need to reset metadata part of the changelog on +trusted.afr.vol-client-1 of /gfs/brick-a/a + +So, the intended changes are: +On /gfs/brick-b/a: +For trusted.afr.vol-client-0 +0x000003b00000000100000000 to 0x000000000000000100000000 +(Note that the metadata part is still not all zeros) +Hence execute +`setfattr -n trusted.afr.vol-client-0 -v 0x000000000000000100000000 /gfs/brick-b/a` + +On /gfs/brick-a/a: +For trusted.afr.vol-client-1 +0x0000000000000000ffffffff to 0x000003d70000000000000000 +(Note that the data part is still not all zeros) +Hence execute +`setfattr -n trusted.afr.vol-client-1 -v 0x000003d70000000000000000 /gfs/brick-a/a` + +Thus after the above operations are done, the changelogs look like this: +``` +[root@pranithk-laptop vol]# getfattr -d -m . -e hex /gfs/brick-?/a +getfattr: Removing leading '/' from absolute path names +\#file: gfs/brick-a/a +trusted.afr.vol-client-0=0x000000000000000000000000 +trusted.afr.vol-client-1=0x000003d70000000000000000 +trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57 + +\#file: gfs/brick-b/a +trusted.afr.vol-client-0=0x000000000000000100000000 +trusted.afr.vol-client-1=0x000000000000000000000000 +trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57 +``` + +Triggering Self-heal: +--------------------- +Perform `ls -l <file-path-on-gluster-mount>` to trigger healing. + +Fixing Directory entry split-brain: +---------------------------------- +Afr has the ability to conservatively merge different entries in the directories +when there is a split-brain on directory. +If on one brick directory 'd' has entries '1', '2' and has entries '3', '4' on +the other brick then afr will merge all of the entries in the directory to have +'1', '2', '3', '4' entries in the same directory. +(Note: this may result in deleted files to re-appear in case the split-brain +happens because of deletion of files on the directory) +Split-brain resolution needs human intervention when there is at least one entry +which has same file name but different gfid in that directory. +Example: +On brick-a the directory has entries '1' (with gfid g1), '2' and on brick-b +directory has entries '1' (with gfid g2) and '3'. +These kinds of directory split-brains need human intervention to resolve. +The user needs to remove either file '1' on brick-a or the file '1' on brick-b +to resolve the split-brain. In addition, the corresponding gfid-link file also +needs to be removed.The gfid-link files are present in the .glusterfs folder +in the top-level directory of the brick. If the gfid of the file is +0x307a5c9efddd4e7c96e94fd4bcdcbd1b (the trusted.gfid extended attribute got +from the getfattr command earlier),the gfid-link file can be found at +`/gfs/brick-a/.glusterfs/30/7a/307a5c9efddd4e7c96e94fd4bcdcbd1b` + +#### Word of caution: +Before deleting the gfid-link, we have to ensure that there are no hard links +to the file present on that brick. If hard-links exist,they must be deleted as +well. diff --git a/doc/debugging/statedump.md b/doc/debugging/statedump.md new file mode 100644 index 00000000000..9dfdce15fad --- /dev/null +++ b/doc/debugging/statedump.md @@ -0,0 +1,414 @@ +# Statedump +Statedump is a file generated by glusterfs process with different data structure state which may contain the active inodes, fds, mempools, iobufs, memory allocation stats of different types of datastructures per xlator etc. + +## How to generate statedump +We can find the directory where statedump files are created using `gluster --print-statedumpdir` command. +Create that directory if not already present based on the type of installation. +Lets call this directory `statedump-directory`. + +We can generate statedump using `kill -USR1 <pid-of-gluster-process>`. +gluster-process is nothing but glusterd/glusterfs/glusterfsd process. + +There are also commands to generate statedumps for brick processes/nfs server/quotad + +For bricks: +``` +gluster volume statedump <volname> +``` + +For nfs server: +``` +gluster volume statedump <volname> nfs +``` + +For quotad: +``` +gluster volume statedump <volname> quotad +``` + +For brick-processes files will be created in `statedump-directory` with name of the file as `hyphenated-brick-path.<pid>.dump.timestamp`. For all other processes it will be `glusterdump.<pid>.dump.timestamp`. + +For applications using libgfapi, `SIGUSR1` cannot be used, eg: smbd/libvirtd +processes could have used the `SIGUSR1` signal already for other purposes. +To generate statedump for the processes, using libgfapi, below command can be +executed from one of the nodes in the gluster cluster to which the libgfapi +application is connected to. +``` +gluster volume statedump <volname> client <hostname>:<process id> +``` +The statedumps can be found in the `statedump-directory`, the name of the +statedumps being `glusterdump.<pid>.dump.timestamp`. For a process there can be +multiple such files created depending on the number of times the volume is +accessed by the process (related to the number of `glfs_init()` calls). + +## How to read statedump +We shall see snippets of each type of statedump. + +First and last lines of the file have starting and ending time of writing the statedump file. Times will be in UTC timezone. + +mallinfo return status is printed in the following format. Please read man mallinfo for more information about what each field means. +### Mallinfo +``` +[mallinfo] +mallinfo_arena=100020224 /* Non-mmapped space allocated (bytes) */ +mallinfo_ordblks=69467 /* Number of free chunks */ +mallinfo_smblks=449 /* Number of free fastbin blocks */ +mallinfo_hblks=13 /* Number of mmapped regions */ +mallinfo_hblkhd=20144128 /* Space allocated in mmapped regions (bytes) */ +mallinfo_usmblks=0 /* Maximum total allocated space (bytes) */ +mallinfo_fsmblks=39264 /* Space in freed fastbin blocks (bytes) */ +mallinfo_uordblks=96710112 /* Total allocated space (bytes) */ +mallinfo_fordblks=3310112 /* Total free space (bytes) */ +mallinfo_keepcost=133712 /* Top-most, releasable space (bytes) */ +``` + +### Data structure allocation stats +For every xlator data structure memory per translator loaded in the call-graph is displayed in the following format: + +For xlator with name: glusterfs +``` +[global.glusterfs - Memory usage] #[global.xlator-name - Memory usage] +num_types=119 #It shows the number of data types it is using +``` + +Now for each data-type it prints the memory usage. + +``` +[global.glusterfs - usage-type gf_common_mt_gf_timer_t memusage] +#[global.xlator-name - usage-type <tag associated with the data-type> memusage] +size=112 #num_allocs times the sizeof(data-type) i.e. num_allocs * sizeof (data-type) +num_allocs=2 #Number of allocations of the data-type which are active at the time of taking statedump. +max_size=168 #max_num_allocs times the sizeof(data-type) i.e. max_num_allocs * sizeof (data-type) +max_num_allocs=3 #Maximum number of active allocations at any point in the life of the process. +total_allocs=7 #Number of times this data is allocated in the life of the process. +``` + +### Mempools + +Mempools are optimization to reduce the number of allocations of a data type. If we create a mem-pool of lets say 1024 elements for a data-type, new elements will be allocated from heap using syscalls like calloc, only if all the 1024 elements in the pool are in active use. + +Memory pool allocated by each xlator is displayed in the following format: + +``` +[mempool] #Section name +-----=----- +pool-name=fuse:fd_t #pool-name=<xlator-name>:<data-type> +hot-count=1 #number of mempool elements that are in active use. i.e. for this pool it is the number of 'fd_t' s in active use. +cold-count=1023 #number of mempool elements that are not in use. If a new allocation is required it will be served from here until all the elements in the pool are in use i.e. cold-count becomes 0. +padded_sizeof=108 #Each mempool element is padded with a doubly-linked-list + ptr of mempool + is-in-use info to operate the pool of elements, this size is the element-size after padding +pool-misses=0 #Number of times the element had to be allocated from heap because all elements from the pool are in active use. +alloc-count=314 #Number of times this type of data is allocated through out the life of this process. This may include pool-misses as well. +max-alloc=3 #Maximum number of elements from the pool in active use at any point in the life of the process. This does *not* include pool-misses. +cur-stdalloc=0 #Denotes the number of allocations made from heap once cold-count reaches 0, that are yet to be released via mem_put(). +max-stdalloc=0 #Maximum number of allocations from heap that are in active use at any point in the life of the process. +``` + +### Iobufs +``` +[iobuf.global] +iobuf_pool=0x1f0d970 #The memory pool for iobufs +iobuf_pool.default_page_size=131072 #The default size of iobuf (if no iobuf size is specified the default size is allocated) +#iobuf_arena: One arena represents a group of iobufs of a particular size +iobuf_pool.arena_size=12976128 # The initial size of the iobuf pool (doesn't include the stdalloc'd memory or the newly added arenas) +iobuf_pool.arena_cnt=8 #Total number of arenas in the pool +iobuf_pool.request_misses=0 #The number of iobufs that were stdalloc'd (as they exceeded the default max page size provided by iobuf_pool). +``` + +There are 3 lists of arenas: + +1. Arena list: arenas allocated during iobuf pool creation and the arenas that are in use(active_cnt != 0) will be part of this list. +2. Purge list: arenas that can be purged(no active iobufs, active_cnt == 0). +3. Filled list: arenas without free iobufs. + +``` +[purge.1] #purge.<S.No.> +purge.1.mem_base=0x7fc47b35f000 #The address of the arena structure +purge.1.active_cnt=0 #The number of iobufs active in that arena +purge.1.passive_cnt=1024 #The number of unused iobufs in the arena +purge.1.alloc_cnt=22853 #Total allocs in this pool(number of times the iobuf was allocated from this arena) +purge.1.max_active=7 #Max active iobufs from this arena, at any point in the life of this process. +purge.1.page_size=128 #Size of all the iobufs in this arena. + +[arena.5] #arena.<S.No.> +arena.5.mem_base=0x7fc47af1f000 +arena.5.active_cnt=0 +arena.5.passive_cnt=64 +arena.5.alloc_cnt=0 +arena.5.max_active=0 +arena.5.page_size=32768 +``` + +If the active_cnt of any arena is non zero, then the statedump will also have the iobuf list. +``` +[arena.6.active_iobuf.1] #arena.<S.No>.active_iobuf.<iobuf.S.No.> +arena.6.active_iobuf.1.ref=1 #refcount of the iobuf +arena.6.active_iobuf.1.ptr=0x7fdb921a9000 #address of the iobuf + +[arena.6.active_iobuf.2] +arena.6.active_iobuf.2.ref=1 +arena.6.active_iobuf.2.ptr=0x7fdb92189000 +``` + +At any given point in time if there are lots of filled arenas then that could be a sign of iobuf leaks. + +### Call stack +All the fops received by gluster are handled using call-stacks. Call stack contains the information about uid/gid/pid etc of the process that is executing the fop. Each call-stack contains different call-frames per xlator which handles that fop. + +``` +[global.callpool.stack.3] #global.callpool.stack.<Serial-Number> +stack=0x7fc47a44bbe0 #Stack address +uid=0 #Uid of the process which is executing the fop +gid=0 #Gid of the process which is executing the fop +pid=6223 #Pid of the process which is executing the fop +unique=2778 #Xlators like afr do copy_frame and perform the operation in a different stack, this id is useful to find out the stacks that are inter-related because of copy-frame +lk-owner=0000000000000000 #Some of the fuse fops have lk-owner. +op=LOOKUP #Fop +type=1 #Type of the op i.e. FOP/MGMT-OP +cnt=9 #Number of frames in this stack. +``` +### Call-frame +Each frame will have information about which xlator the frame belongs to, what is the function it wound to/from and will be unwind to. It also mentions if the unwind happened or not. If we observe hangs in the system and want to find out which xlator is causing it. Take a statedump and see what is the final xlator which is yet to be unwound. + +``` +[global.callpool.stack.3.frame.2]#global.callpool.stack.<stack-serial-number>.frame.<frame-serial-number> +frame=0x7fc47a611dbc #Frame address +ref_count=0 #Incremented at the time of wind and decremented at the time of unwind. +translator=r2-client-1 #Xlator this frame belongs to +complete=0 #if this value is 1 that means this frame is already unwound. 0 if it is yet to unwind. +parent=r2-replicate-0 #Parent xlator of this frame +wind_from=afr_lookup #Parent xlator function from which the wind happened +wind_to=priv->children[i]->fops->lookup +unwind_to=afr_lookup_cbk #Parent xlator function to which unwind happened +``` + +### History of operations in Fuse + +Fuse maintains history of operations that happened in fuse. + +``` +[xlator.mount.fuse.history] +TIME=2014-07-09 16:44:57.523364 +message=[0] fuse_release: RELEASE(): 4590:, fd: 0x1fef0d8, gfid: 3afb4968-5100-478d-91e9-76264e634c9f + +TIME=2014-07-09 16:44:57.523373 +message=[0] send_fuse_err: Sending Success for operation 18 on inode 3afb4968-5100-478d-91e9-76264e634c9f + +TIME=2014-07-09 16:44:57.523394 +message=[0] fuse_getattr_resume: 4591, STAT, path: (/iozone.tmp), gfid: (3afb4968-5100-478d-91e9-76264e634c9f) +``` + +### Xlator configuration +``` +[cluster/replicate.r2-replicate-0] #Xlator type, name information +child_count=2 #Number of children to the xlator +#Xlator specific configuration below +child_up[0]=1 +pending_key[0]=trusted.afr.r2-client-0 +child_up[1]=1 +pending_key[1]=trusted.afr.r2-client-1 +data_self_heal=on +metadata_self_heal=1 +entry_self_heal=1 +data_change_log=1 +metadata_change_log=1 +entry-change_log=1 +read_child=1 +favorite_child=-1 +wait_count=1 +``` + +### Graph/inode table +``` +[active graph - 1] + +conn.1.bound_xl./data/brick01a/homegfs.hashsize=14057 +conn.1.bound_xl./data/brick01a/homegfs.name=/data/brick01a/homegfs/inode +conn.1.bound_xl./data/brick01a/homegfs.lru_limit=16384 #Least recently used size limit +conn.1.bound_xl./data/brick01a/homegfs.active_size=690 #Number of inodes undergoing some kind of fop to be precise on which there is at least one ref. +conn.1.bound_xl./data/brick01a/homegfs.lru_size=183 #Number of inodes present in lru list +conn.1.bound_xl./data/brick01a/homegfs.purge_size=0 #Number of inodes present in purge list +``` + +### Inode +``` +[conn.1.bound_xl./data/brick01a/homegfs.active.324] #324th inode in active inode list +gfid=e6d337cf-97eb-44b3-9492-379ba3f6ad42 #Gfid of the inode +nlookup=13 #Number of times lookups happened from the client or from fuse kernel +fd-count=4 #Number of fds opened on the inode +ref=11 #Number of refs taken on the inode +ia_type=1 #Type of the inode. This should be changed to some string :-( +Ref by xl:.patchy-md-cache=11 #Further this there will be a list of xlators, and the ref count taken by each of them on this inode at the time of statedump + +[conn.1.bound_xl./data/brick01a/homegfs.lru.1] #1st inode in lru list. Note that ref count is zero for these inodes. +gfid=5114574e-69bc-412b-9e52-f13ff087c6fc +nlookup=5 +fd-count=0 +ref=0 +ia_type=2 +Ref by xl:.fuse=1 +Ref by xl:.patchy-client-0=-1 +``` +### Inode context +For each inode per xlator some context could be stored. This context can also be printed in the statedump. Here is the inode ctx of locks xlator +``` +[xlator.features.locks.homegfs-locks.inode] +path=/homegfs/users/dfrobins/gfstest/r4/SCRATCH/fort.5102 - path of the file +mandatory=0 +inodelk-count=5 #Number of inode locks +lock-dump.domain.domain=homegfs-replicate-0:self-heal #Domain name where self-heals take locks to prevent more than one heal on the same file +inodelk.inodelk[0](ACTIVE)=type=WRITE, whence=0, start=0, len=0, pid = 18446744073709551615, owner=080b1ada117f0000, client=0xb7fc30, connection-id=compute-30-029.com-3505-2014/06/29-14:46:12:477358-homegfs-client-0-0-1, granted at Sun Jun 29 11:01:00 2014 #Active lock information + +inodelk.inodelk[1](BLOCKED)=type=WRITE, whence=0, start=0, len=0, pid = 18446744073709551615, owner=c0cb091a277f0000, client=0xad4f10, connection-id=gfs01a.com-4080-2014/06/29-14:41:36:917768-homegfs-client-0-0-0, blocked at Sun Jun 29 11:04:44 2014 #Blocked lock information + +lock-dump.domain.domain=homegfs-replicate-0:metadata #Domain name where metadata operations take locks to maintain replication consistency +lock-dump.domain.domain=homegfs-replicate-0 #Domain name where entry/data operations take locks to maintain replication consistency +inodelk.inodelk[0](ACTIVE)=type=WRITE, whence=0, start=11141120, len=131072, pid = 18446744073709551615, owner=080b1ada117f0000, client=0xb7fc30, connection-id=compute-30-029.com-3505-2014/06/29-14:46:12:477358-homegfs-client-0-0-1, granted at Sun Jun 29 11:10:36 2014 #Active lock information +``` + +## FAQ +### How to debug Memory leaks using statedump? + +#### Using memory accounting feature: + +[Bug 1120151](https://bugzilla.redhat.com/show_bug.cgi?id=1120151) is one of the bugs which was debugged using statedump to see which data-structure is leaking. Here is the process used to find what the leak is using statedump. According to the bug the observation is that the process memory usage is increasing whenever one of the bricks is wiped in a replicate volume and a `full` self-heal is invoked to heal the contents. Statedump of the process is taken using `kill -USR1 <pid-of-gluster-self-heal-daemon>`. +``` +grep -w num_allocs glusterdump.5225.dump.1405493251 +num_allocs=77078 +num_allocs=87070 +num_allocs=117376 +.... + +grep hot-count glusterdump.5225.dump.1405493251 +hot-count=16384 +hot-count=16384 +hot-count=4095 +.... + +Find the occurrences in the statedump file to figure out the tags. +``` +grep of the statedump revealed too many allocations for the following data-types under replicate, + +1. gf_common_mt_asprintf +2. gf_common_mt_char +3. gf_common_mt_mem_pool. + +After checking afr-code for allocations with tag `gf_common_mt_char` found `data-self-heal` code path does not free one such allocated memory. `gf_common_mt_mem_pool` suggests that there is a leak in pool memory. `replicate-0:dict_t`, `glusterfs:data_t` and `glusterfs:data_pair_t` pools are using lot of memory, i.e. cold_count is `0` and too many allocations. Checking source code of dict.c revealed that `key` in `dict` is allocated with `gf_common_mt_char` i.e. `2.` tag and value is created using gf_asprintf which in-turn uses `gf_common_mt_asprintf` i.e. `1.`. Browsing the code for leak in self-heal code paths lead to a line which over-writes a variable with new dictionary even when it was already holding a reference to another dictionary. After fixing these leaks, ran the same test to verify that none of the `num_allocs` are increasing even after healing 10,000 files directory hierarchy in statedump of self-heal daemon. +Please check this [patch](http://review.gluster.org/8316) for more info about the fix. + +#### Debugging leaks in memory pools: +Statedump output of memory pools was used to test and verify the fixes to [Bug 1134221](https://bugzilla.redhat.com/show_bug.cgi?id=1134221). On code analysis, dict_t objects were found to be leaking (in terms of not being unref'd enough number of times, during name self-heal. The test involved creating 100 files on plain replicate volume, removing them from one of the brick's backend, and then triggering lookup on them from the mount point. Statedump of the mount process was taken before executing the test case and after it, after compiling glusterfs with -DDEBUG flags (to have cold count set to 0 by default). + +Statedump output of the fuse mount process before the test case was executed: + +``` + +pool-name=glusterfs:dict_t +hot-count=0 +cold-count=0 +padded_sizeof=140 +alloc-count=33 +max-alloc=0 +pool-misses=33 +cur-stdalloc=14 +max-stdalloc=18 + +``` +Statedump output of the fuse mount process after the test case was executed: + +``` + +pool-name=glusterfs:dict_t +hot-count=0 +cold-count=0 +padded_sizeof=140 +alloc-count=2841 +max-alloc=0 +pool-misses=2841 +cur-stdalloc=214 +max-stdalloc=220 + +``` +Here, with cold count being 0 by default, `cur-stdalloc` indicated the number of `dict_t` objects that were allocated in heap using `mem_get()`, and yet to be freed using `mem_put()` (refer to this [page](../developer-guide/datastructure-mem-pool.md) for more details on how mempool works). After the test case (name selfheal of 100 files), there was a rise in the cur-stdalloc value (from 14 to 214) for `dict_t`. + +After these leaks were fixed, glusterfs was again compiled with -DDEBUG flags, and the same steps were performed again and statedump was taken before and after executing the test case, of the mount. This was done to ascertain the validity of the fix. And the following are the results: + +Statedump output of the fuse mount process before executing the test case: + +``` +pool-name=glusterfs:dict_t +hot-count=0 +cold-count=0 +padded_sizeof=140 +alloc-count=33 +max-alloc=0 +pool-misses=33 +cur-stdalloc=14 +max-stdalloc=18 + +``` +Statedump output of the fuse mount process after executing the test case: + +``` +pool-name=glusterfs:dict_t +hot-count=0 +cold-count=0 +padded_sizeof=140 +alloc-count=2837 +max-alloc=0 +pool-misses=2837 +cur-stdalloc=14 +max-stdalloc=119 + +``` +The value of cur-stdalloc remained 14 before and after the test, indicating that the fix indeed does what it's supposed to do. + +### How to debug hangs because of frame-loss? +[Bug 994959](https://bugzilla.redhat.com/show_bug.cgi?id=994959) is one of the bugs where statedump was helpful in finding where the frame was lost. Here is the process used to find where the hang is using statedump. +When the hang was observed, statedumps are taken for all the processes. On mount's statedump the following stack is shown: +``` +[global.callpool.stack.1.frame.1] +ref_count=1 +translator=fuse +complete=0 + +[global.callpool.stack.1.frame.2] +ref_count=0 +translator=r2-client-1 +complete=1 <<----- Client xlator completed the readdirp call and unwound to afr +parent=r2-replicate-0 +wind_from=afr_do_readdir +wind_to=children[call_child]->fops->readdirp +unwind_from=client3_3_readdirp_cbk +unwind_to=afr_readdirp_cbk + +[global.callpool.stack.1.frame.3] +ref_count=0 +translator=r2-replicate-0 +complete=0 <<---- Afr xlator is not unwinding for some reason. +parent=r2-dht +wind_from=dht_do_readdir +wind_to=xvol->fops->readdirp +unwind_to=dht_readdirp_cbk + +[global.callpool.stack.1.frame.4] +ref_count=1 +translator=r2-dht +complete=0 +parent=r2-io-cache +wind_from=ioc_readdirp +wind_to=FIRST_CHILD(this)->fops->readdirp +unwind_to=ioc_readdirp_cbk + +[global.callpool.stack.1.frame.5] +ref_count=1 +translator=r2-io-cache +complete=0 +parent=r2-quick-read +wind_from=qr_readdirp +wind_to=FIRST_CHILD (this)->fops->readdirp +unwind_to=qr_readdirp_cbk + +``` +`unwind_to` shows that call was unwound to `afr_readdirp_cbk` from client xlator. +Inspecting that function revealed that afr is not unwinding the stack when fop failed. +Check this [patch](http://review.gluster.org/5531) for more info about the fix. diff --git a/doc/developer-guide/Language-Bindings.md b/doc/developer-guide/Language-Bindings.md new file mode 100644 index 00000000000..951f5fae2f6 --- /dev/null +++ b/doc/developer-guide/Language-Bindings.md @@ -0,0 +1,45 @@ +# Language Bindings +GlusterFS 3.4 introduced the libgfapi client API for C programs. This +page lists bindings to the libgfapi C library from other languages. + +Go +-- + +- [gogfapi](https://github.com/gluster/gogfapi) - Go language bindings + for libgfapi, aiming to provide an api consistent with the default + Go file apis. + +Java +---- + +- [libgfapi-jni](https://github.com/semiosis/libgfapi-jni/) - Low + level JNI binding for libgfapi +- [glusterfs-java-filesystem](https://github.com/semiosis/glusterfs-java-filesystem) + - High level NIO.2 FileSystem Provider implementation for the Java + platform +- [libgfapi-java-io](https://github.com/gluster/libgfapi-java-io) - + Java bindings for libgfapi, similar to java.io + +Python +------ + +- [libgfapi-python](https://github.com/gluster/libgfapi-python) - + Libgfapi bindings for Python + +Ruby +---- + +- [libgfapi-ruby](https://github.com/spajus/libgfapi-ruby) - Libgfapi + bindings for Ruby using FFI + +Rust +---- + +- [gfapi-sys](https://github.com/cholcombe973/Gfapi-sys) - Libgfapi + bindings for Rust using FFI + +Perl +---- + +- [libgfapi-perl](https://github.com/gluster/libgfapi-perl) - Libgfapi + bindings for Perl using FFI diff --git a/doc/developer-guide/README.md b/doc/developer-guide/README.md new file mode 100644 index 00000000000..aaf9c7476b0 --- /dev/null +++ b/doc/developer-guide/README.md @@ -0,0 +1,81 @@ +Developers +========== + +### From GlusterDocumentation + +Contributing to the Gluster community +------------------------------------- + +Are you itching to send in patches and participate as a developer in the +Gluster community? Here are a number of starting points for getting +involved. We don't require a signed contributor license agreement or +copyright assignment, but we do require a "signed-off-by" line on each +code check-in. + +- [License + Change](http://www.gluster.org/2012/05/glusterfs-license-change/) - + we recently changed the client library code to a dual license under + the GPL v2 and the LGPL v3 or later +- [GlusterFS Coding Standards](./coding-standard.md) + +- If you are not sure of where to start, and what to do, we have a small + write-up on what you can pick. [Check it out](./options-to-contribute.md) + + +Adding File operations +---------------------- + +- [Steps to be followed when adding a new FOP to GlusterFS ](./adding-fops.md) + +Automatic File Replication +-------------------------- + +- [Cluster/afr translator](./afr.md) +- [History of Locking in AFR](./afr-locks-evolution.md) +- [Self heal Daemon](./afr-self-heal-daemon.md) + +Data Structures +--------------- + +- [inode data structure](./datastructure-inode.md) +- [iobuf data structure](./datastructure-iobuf.md) +- [mem-pool data structure](./datastructure-mem-pool.md) + +Find the gfapi symbol versions [here](./gfapi-symbol-versions.md) + +Daemon Management Framework +--------------------------- + +- [How to introduce new daemons using daemon management framework](./daemon-management-framework.md) + +Translators +----------- + +- [Performance/write-Behind Translator](./write-behind.md) +- [Translator Development](./translator-development.md) +- [Storage/posix Translator](./posix.md) + + +Brick multiplex +--------------- + +- [Brick mux resource reduction](./brickmux-thread-reduction.md) + +Fuse +---- + +- [Interrupt handling](./fuse-interrupt.md) + +Testing/Debugging +----------------- + +- [Unit Tests in GlusterFS](./unittest.md) +- [Using the Gluster Test + Framework](./Using-Gluster-Test-Framework.md) - Step by + step instructions for running the Gluster Test Framework +- [Coredump Analysis](../debugging/analyzing-regression-cores.md) - Steps to analize coredumps generated by regression machines. +- [Identifying Resource Leaks](./identifying-resource-leaks.md) + +Release Process +--------------- +- [Versioning](./versioning.md) diff --git a/doc/developer-guide/Using-Gluster-Test-Framework.md b/doc/developer-guide/Using-Gluster-Test-Framework.md new file mode 100644 index 00000000000..d2bb1c391da --- /dev/null +++ b/doc/developer-guide/Using-Gluster-Test-Framework.md @@ -0,0 +1,271 @@ +# USing Gluster Test Framwork +Description +----------- + +The Gluster Test Framework, is a suite of scripts used for regression +testing of Gluster. + +It runs well on RHEL and CentOS (possibly Fedora too, presently being +tested), and is automatically run against every patch submitted to +Gluster [for review](http://review.gluster.org). + +The Gluster Test Framework is part of the main Gluster code base, living +under the "tests" subdirectory: + + http://git.gluster.org/?p=glusterfs.git;a=summary + +WARNING +------- + +Running the Gluster Test Framework deletes “/var/lib/glusterd/\*”. + +**DO NOT run it on a server with any data.** + +Preparation steps for Ubuntu 14.04 LTS +-------------------------------------- + +1. \# apt-get install dbench git libacl1-dev mock nfs-common +nfs-kernel-server libtest-harness-perl libyajl-dev xfsprogs psmisc attr +acl lvm2 rpm + +2. \# apt-get install python-webob python-paste python-sphinx + +3. \# apt-get install autoconf automake bison dos2unix flex libfuse-dev +libaio-dev libibverbs-dev librdmacm-dev libtool libxml2-dev +libxml2-utils liblvm2-dev make libssl-dev pkg-config libpython-dev +python-eventlet python-netifaces python-simplejson python-pyxattr +libreadline-dev tar + +4) Install cmockery2 from github (https://github.com/lpabon/cmockery2) +and compile and make install as in Readme + +5) + + sudo groupadd mock + sudo useradd -g mock mock + +6) mkdir /var/run/gluster + +**Note**: redhat-rpm-config package is not found in ubuntu + +Preparation steps for CentOS 7 (only) +------------------------------------- + +1. Install EPEL: + + $ sudo yum install -y http://epel.mirror.net.in/epel/7/x86_64/e/epel-release-7-1.noarch.rpm + +2. Install the CentOS 7.x dependencies: + + $ sudo yum install -y --enablerepo=epel cmockery2-devel dbench git libacl-devel mock nfs-utils perl-Test-Harness yajl xfsprogs psmisc + + $ sudo yum install -y --enablerepo=epel python-webob1.0 python-paste-deploy1.5 python-sphinx10 redhat-rpm-config + +==\> Despite below missing packages it worked for me + + No package python-webob1.0 available. + No package python-paste-deploy1.5 available. + No package python-sphinx10 available. + + $ sudo yum install -y --enablerepo=epel autoconf automake bison dos2unix flex fuse-devel libaio-devel libibverbs-devel \ + librdmacm-devel libtool libxml2-devel lvm2-devel make openssl-devel pkgconfig \ + python-devel python-eventlet python-netifaces python-paste-deploy \ + python-simplejson python-sphinx python-webob pyxattr readline-devel rpm-build \ + tar + +3. Create the mock user + + $ sudo useradd -g mock mock + +Preparation steps for CentOS 6.3+ (only) +---------------------------------------- + +1. Install EPEL: + + $ sudo yum install -y http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm + +2. Install the CentOS 6.x dependencies: + + $ sudo yum install -y --enablerepo=epel cmockery2-devel dbench git libacl-devel mock nfs-utils perl-Test-Harness yajl xfsprogs + $ sudo yum install -y --enablerepo=epel python-webob1.0 python-paste-deploy1.5 python-sphinx10 redhat-rpm-config + $ sudo yum install -y --enablerepo=epel autoconf automake bison dos2unix flex fuse-devel libaio-devel libibverbs-devel \ + librdmacm-devel libtool libxml2-devel lvm2-devel make openssl-devel pkgconfig \ + python-devel python-eventlet python-netifaces python-paste-deploy \ + python-simplejson python-sphinx python-webob pyxattr readline-devel rpm-build \ + tar + +3. Create the mock user + + $ sudo useradd -g mock mock + +Preparation steps for RHEL 6.3+ (only) +-------------------------------------- + +1. Ensure you have the "Scalable Filesystem Support" group installed + +This provides the xfsprogs package, which is required by the test +framework. + +2. Install EPEL: + + $ sudo yum install -y http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm + +3. Install the CentOS 6.x dependencies: + + $ sudo yum install -y --enablerepo=epel cmockery2-devel dbench git libacl-devel mock nfs-utils yajl perl-Test-Harness + $ sudo yum install -y --enablerepo=rhel-6-server-optional-rpms python-webob1.0 python-paste-deploy1.5 python-sphinx10 redhat-rpm-config + $ sudo yum install -y --disablerepo=rhs* --enablerepo=*optional-rpms autoconf \ + automake bison dos2unix flex fuse-devel libaio-devel libibverbs-devel \ + librdmacm-devel libtool libxml2-devel lvm2-devel make openssl-devel pkgconfig \ + python-devel python-eventlet python-netifaces python-paste-deploy \ + python-simplejson python-sphinx python-webob pyxattr readline-devel rpm-build \ + tar + +4. Create the mock user + + $ sudo useradd -g mock mock + +Preparation steps for Fedora 16-19 (only) +----------------------------------------- + +**Still in development** + +1. Install the Fedora dependencies: + + $ sudo yum install -y attr cmockery2-devel dbench git mock nfs-utils perl-Test-Harness psmisc xfsprogs + $ sudo yum install -y python-webob1.0 python-paste-deploy1.5 python-sphinx10 redhat-rpm-config + $ sudo yum install -y autoconf automake bison dos2unix flex fuse-devel libaio-devel libibverbs-devel \ + librdmacm-devel libtool libxml2-devel lvm2-devel make openssl-devel pkgconfig \ + python-devel python-eventlet python-netifaces python-paste-deploy \ + python-simplejson python-sphinx python-webob pyxattr readline-devel rpm-build \ + tar + +3. Create the mock user + + $ sudo useradd -g mock mock + +Common steps +------------ + +1. Ensure DNS for your server is working + +The Gluster Test Framework fails miserably if the full domain name for +your server doesn't resolve back to itself. + +If you don't have a working DNS infrastructure in place, adding an entry +for your server to its /etc/hosts file will work. + +2. Install the version of Gluster you are testing + +Either install an existing set of rpms: + + $ sudo yum install [your gluster rpms here] + +Or compile your own ones (fairly easy): + + http://www.gluster.org/community/documentation/index.php/CompilingRPMS + +3. Clone the GlusterFS git repository + + $ git clone git://git.gluster.org/glusterfs + $ cd glusterfs + +Ensure mock can access the directory +------------------------------------ + +Some tests run as the user "mock". If the mock user can't access the +tests subdirectory directory, these tests fail. (rpm.t is one such test) + +This is a known gotcha when the git repo is cloned to your home +directory. Home directories generally don't have world readable +permissions. You can fix this by adjusting your home directory +permissions, or placing the git repo somewhere else (with access for the +mock user). + +Running the tests +----------------- + +The tests need to run as root, so they can mount volumes and manage +gluster processes as needed. + +It's also best to run them directly as the root user, instead of through +sudo. Strange things sporadicly happen (for me) when using the full test +framework through sudo, that haven't happened (yet) when running +directly as root. Hangs in dbench particularly, which are part of at +least one test. + + # ./run-tests.sh + +The test framework takes just over 45 minutes to run in a VM here (4 +cpu's assigned, 8GB ram, SSD storage). It may take significantly more or +less time for you, depending on the hardware and software you're using. + +Showing debug information +------------------------- + +To display verbose information while the tests are running, set the +DEBUG environment variable to 1 prior to running the tests. + + # DEBUG=1 ./run-tests.sh + +Log files +--------- + +Verbose output from the rpm.t test goes into "rpmbuild-mock.log", +located in the same directory the test is run from. + +Reporting bugs +-------------- + +If you hit a bug when running the test framework, **please** create a +bug report for it on Bugzilla so it gets fixed: + + https://bugzilla.redhat.com/enter_bug.cgi?product=GlusterFS&component=tests + +Creating your own tests +----------------------- + +The test scripts are written in bash, with their filenames ending in .t +instead of .sh. + +When creating your own test scripts, create them in an appropriate +subdirectory under "tests" (eg "bugs" or "features") and use descriptive +names like "bug-XXXXXXX-checking-feature-X.t" + +Also include the "include.rc" file, which defines the test types and +host/brick/volume defaults: + + . $(dirname $0)/../include.rc + +There are 5 test types available at present, but feel free to add more +if you need something that doesn't yet exist. The test types are +explained in more detail below. + +Also essential is the "cleanup" command, which removes any existing +Gluster configuration (**without backing it up**), and also kills any +running gluster processes. + +There is a basic test template you can copy, named bug-000000.t in the +bugs subdirectory: + + $ cp bugs/bug-000000.t somedir/descriptive-name.t + +### TEST + +- Example of usage in basic/volume.t + +### TEST\_IN\_LOOP + +- Example of usage in basic/rpm.t + +### EXPECT + +- Example of usage in basic/volume.t + +### EXPECT\_WITHIN + +- Example of usage in basic/volume-status.t + +### EXPECT\_KEYWORD + +- Defined in include.rc, but seems to be unused? diff --git a/doc/developer-guide/adding-fops.md b/doc/developer-guide/adding-fops.md new file mode 100644 index 00000000000..3f72ed3e23a --- /dev/null +++ b/doc/developer-guide/adding-fops.md @@ -0,0 +1,18 @@ +Adding a new FOP +================ + +Steps to be followed when adding a new FOP to GlusterFS: + +1. Edit `glusterfs.h` and add a `GF_FOP_*` constant. +2. Edit `xlator.[ch]` and: + * add the new prototype for fop and callback. + * edit `xlator_fops` structure. +3. Edit `xlator.c` and add to fill_defaults. +4. Edit `protocol.h` and add struct necessary for the new FOP. +5. Edit `defaults.[ch]` and provide default implementation. +6. Edit `call-stub.[ch]` and provide stub implementation. +7. Edit `common-utils.c` and add to gf_global_variable_init(). +8. Edit client-protocol and add your FOP. +9. Edit server-protocol and add your FOP. +10. Implement your FOP in any translator for which the default implementation + is not sufficient. diff --git a/doc/developer-guide/afr-locks-evolution.md b/doc/developer-guide/afr-locks-evolution.md new file mode 100644 index 00000000000..2dabbcfeb13 --- /dev/null +++ b/doc/developer-guide/afr-locks-evolution.md @@ -0,0 +1,91 @@ +History of locking in AFR +-------------------------- + +GlusterFS has **locks** translator which provides the following internal locking operations called `inodelk`, `entrylk` which are used by afr to achieve synchronization of operations on files or directories that conflict with each other. + +`Inodelk` gives the facility for translators in GlusterFS to obtain range (denoted by tuple with **offset**, **length**) locks in a given **domain** for an inode. +Full file lock is denoted by the tuple (offset: `0`, length: `0`) i.e. length `0` is considered as infinity. + +`Entrylk` enables translators of GlusterFS to obtain locks on `name` in a given **domain** for an inode, typically a directory. + +The **locks** translator provides both *blocking* and *nonblocking* variants and of these locks. + + +AFR makes use of locks xlator extensively: + +1)For FOPS (from clients) +----------------------- +* Data transactions take inode locks on data domain, Let's refer to this domain name as DATA_DOMAIN. + + So locking for writes would be something like this:`inodelk(offset,length, DATA_DOMAIN)` + For truncating a file to zero, it would be `inodelk(0,0,DATA_DOMAIN)` + +* Metadata transactions (chown/chmod) also take inode locks but on a special range on metadata domain, + i.e.`(LLONG_MAX-1 , 0, METADATA_DOMAIN).` + +* Entry transactions (create, mkdir, rmdir,unlink, symlink, link,rename) take entrylk on `(name, parent inode)`. + + +2)For self heal: +------------- +* For Metadata self-heal, it is the same. i.e.`inodelk(LLONG_MAX-1 , 0, METADATA_DOMAIN)`. +* For Entry self-heal, it is `entrylk(NULL name, parent inode)`. Specifying NULL for the name takes full lock on the directory referred to by the inode. +* For data self-heal, there is a bit of history as to how locks evolved: + +### Initial version (say version 1) : +There was no concept of selfheal daemon (shd). Only client lookups triggered heals. so AFR always took `inodelk(0,0,DATA_DOMAIN)` for healing. The issue with this approach was that when heal was in progress, I/O from clients was blocked . + +### version 2: +shd was introduced. We needed to allow I/O to go through when heal was going,provided the ranges did not overlap. To that extent, the following approach was adopted: + ++ 1.shd takes (full inodelk in DATA_DOMAIN). Thus client FOPS are blocked and cannot modify changelog-xattrs ++ 2.shd inspects xattrs to determine source/sink ++ 3.shd takes a chunk inodelk(0-128kb) again in DATA_DOMAIN (locks xlator allows overlapping locks if lock owner is the same). ++ 4.unlock full lock ++ 5.heal ++ 6.take next chunk lock(129-256kb) ++ 7.unlock 1st chunk lock, heal the second chunk and so on. + + +Thus after 4, any client FOP could write to regions that was not currently under heal. The exception was truncate (to size 0) because it needs full file lock and will always block because some chunk is always under lock by the shd until heal completes. + +Another issue was that 2 shds could run in parallel. Say SHD1 and SHD2 compete for step 1. Let SHD1 win. It proceeds and completes step 4. Now SHD2 also succeeds in step 1, continues all steps. Thus at the end both shds will decrement the changelog leading to negative values in it) + +### version 3 +To prevent parallel self heals, another domain was introduced, let us call it SELF_HEAL_DOMAIN. With this domain, the following approach was adopted and is **the approach currently in use**: + ++ 1.shd takes (full inodelk on SELF_HEAL_DOMAIN) ++ 2.shd takes (full inodelk on DATA_DOMAIN) ++ 3.shd inspects xattrs to determine source/sink ++ 4.unlock full lock on DATA_DOMAIN ++ 5.take chunk lock(0-128kb) on DATA_DOMAIN ++ 6.heal ++ 7.take next chunk lock(129-256kb) on DATA_DOMAIN ++ 8.unlock 1st chunk lock, heal and so on. ++ 9.Finally release full lock on SELF_HEAL_DOMAIN + +Thus until one shd completes step 9, another shd cannot start step 1, solving the problem of simultaneous heals. +Note that the issue of truncate (to zero) FOP hanging still remains. +Also there are multiple network calls involved in this scheme. (lock,heal(ie read+write), unlock) per chunk. i.e 4 calls per chunk. + +### version 4 (ToDo) +Some improvements that need to be made in version 3: +* Reduce network calls using piggy backing. +* After taking chunk lock and healing, we need to unlock the lock before locking the next chunk. This gives a window for any pending truncate FOPs to succeed. If truncate succeeds, the heal of next chunk will fail (read returns zero) +and heal is stopped. *BUT* there is **yet another** issue: + +* shd does steps 1 to 4. Let's assume source is brick b1, sink is brick b2 . i.e xattrs are (0,1) and (0,0) on b1 and b2 respectively. Now before shd takes (0-128kb) lock, a client FOP takes it. +It modifies data but the FOP succeeds only on brick 2. writev returns success, and the attrs now read (0,1) (1,0). SHD takes over and heals. It had observed (0,1),(0,0) earlier +and thus goes ahead and copies stale 128Kb from brick 1 to brick2. Thus as far as application is concerned, `writev` returned success but bricks have stale data. +What needs to be done is `writev` must return success only if it succeeded on atleast one source brick (brick b1 in this case). Otherwise The heal still happens in reverse direction but as far as the application is concerned, it received an error. + +### Note on lock **domains** +We have used conceptual names in this document like DATA_DOMAIN/ METADATA_DOMAIN/ SELF_HEAL_DOMAIN. In the code, these are mapped to strings that are based on the AFR xlator name like so: + +DATA_DOMAIN --->"vol_name-replicate-n" + +METADATA_DOMAIN --->"vol_name-replicate-n:metadata" + +SELF_HEAL_DOMAIN -->"vol_name-replicate-n:self-heal" + +where vol_name is the name of the volume and 'n' is the replica subvolume index (starting from 0). diff --git a/doc/developer-guide/afr-self-heal-daemon.md b/doc/developer-guide/afr-self-heal-daemon.md new file mode 100644 index 00000000000..65940d420b7 --- /dev/null +++ b/doc/developer-guide/afr-self-heal-daemon.md @@ -0,0 +1,92 @@ +Self-Heal Daemon +================ +The self-heal daemon (shd) is a glusterfs process that is responsible for healing files in a replicate/ disperse gluster volume. +Every server (brick) node of the volume runs one instance of the shd. So even if one node contains replicate/ disperse bricks of +multiple volumes, it would be healed by the same shd. + +This document only describes how the shd works for replicate (AFR) volumes. + +The shd is launched by glusterd when the volume starts (only if the volume includes a replicate configuration). The graph +of the shd process in every node contains the following: The io-stats which is the top most xlator, its children being the +replicate xlators (subvolumes) of *only* the bricks present in that particular node, and finally *all* the client xlators that are the children of the replicate xlators. + +The shd does two types of self-heal crawls: Index heal and Full heal. For both these types of crawls, the basic idea is the same: +For each file encountered while crawling, perform metadata, data and entry heals under appropriate locks. +* An overview of how each of these heals is performed is detailed in the 'Self-healing' section of *doc/features/afr-v1.md* +* The different file locks which the shd takes for each of these heals is detailed in *doc/developer +-guide/afr-locks-evolution.md* + +Metadata heal refers to healing extended attributes, mode and permissions of a file or directory. +Data heal refers to healing the file contents. +Entry self-heal refers to healing entries inside a directory. + +Index heal +========== +The index heal is done: + a) Every 600 seconds (can be changed via the `cluster.heal-timeout` volume option) + b) When it is explicitly triggered via the `gluster vol heal <VOLNAME>` command + c) Whenever a replica brick that was down comes back up. + +Only one heal can be in progress at one time, irrespective of reason why it was triggered. If another heal is triggered before the first one completes, it will be queued. +Only one heal can be queued while the first one is running. If an Index heal is queued, it can be overridden by queuing a Full heal and not vice-versa. Also, before processing +each entry in index heal, a check is made if a full heal is queued. If it is, then the index heal is aborted so that the full heal can proceed. + +In index heal, each shd reads the entries present inside .glusterfs/indices/xattrop/ folder and triggers heal on each entry with appropriate locks. +The .glusterfs/indices/xattrop/ directory contains a base entry of the name "xattrop-<virtual-gfid-string>". All other entries are hardlinks to the base entry. The +*names* of the hardlinks are the gfid strings of the files that may need heal. + +When a client (mount) performs an operation on the file, the index xlator present in each brick process adds the hardlinks in the pre-op phase of the FOP's transaction +and removes it in post-op phase if the operation is successful. Thus if an entry is present inside the .glusterfs/indices/xattrop/ directory when there is no I/O +happening on the file, it means the file needs healing (or atleast an examination if the brick crashed after the post-op completed but just before the removal of the hardlink). + +#### Index heal steps: +<pre><code> +In shd process of *each node* { + opendir +readdir (.glusterfs/indices/xattrop/) + for each entry inside it { + self_heal_entry() //Explained below. + } +} +</code></pre> + +<pre><code> +self_heal_entry() { + Call syncop_lookup(replicae subvolume) which eventually does { + take appropriate locks + determine source and sinks from AFR changelog xattrs + perform whatever heal is needed (any of metadata, data and entry heal in that order) + clear changelog xattrs and hardlink inside .glusterfs/indices/xattrop/ + } +} +</code></pre> + +Note: +* If the gfid hardlink is present in the .glusterfs/indices/xattrop/ of both replica bricks, then each shd will try to heal the file but only one of them will be able to proceed due to the self-heal domain lock. + +* While processing entries inside .glusterfs/indices/xattrop/, if shd encounters an entry whose parent is yet to be healed, it will skip it and it will be picked up in the next crawl. + +* If a file is in data/ metadata split-brain, it will not be healed. + +* If a directory is in entry split-brain, a conservative merge will be performed, wherein after the merge, the entries of the directory will be a union of the entries in the replica pairs. + +Full heal +========= +A full heal is triggered by running `gluster vol heal <VOLNAME> full`. This command is usually run in disk replacement scenarios where the entire data is to be copied from one of the healthy bricks of the replica to the brick that was just replaced. + +Unlike the index heal which runs on the shd of every node in a replicate subvolume, the full heal is run only on the shd of one node per replicate subvolume: the node having the highest UUID. +i.e In a 2x2 volume made of 4 nodes N1, N2, N3 and N4, If UUID of N1>N2 and UUID N4 >N3, then the full crawl is carried out by the shds of N1 and N4.(Node UUID can be found in `/var/lib/glusterd/glusterd.info`) + +The full heal steps are almost identical to the index heal, except the heal is performed on each replica starting from the root of the volume: +<pre><code> +In shd process of *highest UUID node per replica* { + opendir +readdir ("/") + for each entry inside it { + self_heal_entry() + if (entry == directory) { + /* Recurse*/ + again opendir+readdir (directory) followed by self_heal_entry() of each entry. + } + + } +} +</code></pre> diff --git a/doc/developer-guide/afr.md b/doc/developer-guide/afr.md new file mode 100644 index 00000000000..566573a4e26 --- /dev/null +++ b/doc/developer-guide/afr.md @@ -0,0 +1,191 @@ +cluster/afr translator +====================== + +Locking +------- + +Before understanding replicate, one must understand two internal FOPs: + +### `GF_FILE_LK` + +This is exactly like `fcntl(2)` locking, except the locks are in a +separate domain from locks held by applications. + +### `GF_DIR_LK (loc_t *loc, char *basename)` + +This allows one to lock a name under a directory. For example, +to lock /mnt/glusterfs/foo, one would use the call: + +``` +GF_DIR_LK ({loc_t for "/mnt/glusterfs"}, "foo") +``` + +If one wishes to lock *all* the names under a particular directory, +supply the basename argument as `NULL`. + +The locks can either be read locks or write locks; consult the +function prototype for more details. + +Both these operations are implemented by the features/locks (earlier +known as posix-locks) translator. + +Basic design +------------ + +All FOPs can be classified into four major groups: + +### inode-read + +Operations that read an inode's data (file contents) or metadata (perms, etc.). + +access, getxattr, fstat, readlink, readv, stat. + +### inode-write + +Operations that modify an inode's data or metadata. + +chmod, chown, truncate, writev, utimens. + +### dir-read + +Operations that read a directory's contents or metadata. + +readdir, getdents, checksum. + +### dir-write + +Operations that modify a directory's contents or metadata. + +create, link, mkdir, mknod, rename, rmdir, symlink, unlink. + +Some of these make a subgroup in that they modify *two* different entries: +link, rename, symlink. + +### Others + +Other operations. + +flush, lookup, open, opendir, statfs. + +Algorithms +---------- + +Each of the four major groups has its own algorithm: + +### inode-read, dir-read + +1. Send a request to the first child that is up: + * if it fails: + * try the next available child + * if we have exhausted all children: + * return failure + +### inode-write + + All operations are done in parallel unless specified otherwise. + +1. Send a ``GF_FILE_LK`` request on all children for a write lock on the + appropriate region + (for metadata operations: entire file (0, 0) for writev: + (offset, offset+size of buffer)) + * If a lock request fails on a child: + * unlock all children + * try to acquire a blocking lock (`F_SETLKW`) on each child, serially. + If this fails (due to `ENOTCONN` or `EINVAL`): + Consider this child as dead for rest of transaction. +2. Mark all children as "pending" on all (alive) children (see below for +meaning of "pending"). + * If it fails on any child: + * mark it as dead (in transaction local state). +3. Perform operation on all (alive) children. + * If it fails on any child: + * mark it as dead (in transaction local state). +4. Unmark all successful children as not "pending" on all nodes. +5. Unlock region on all (alive) children. + +### dir-write + + The algorithm for dir-write is same as above except instead of holding + `GF_FILE_LK` locks we hold a GF_DIR_LK lock on the name being operated upon. + In case of link-type calls, we hold locks on both the operand names. + +"pending" +--------- + +The "pending" number is like a journal entry. A pending entry is an +array of 32-bit integers stored in network byte-order as the extended +attribute of an inode (which can be a directory as well). + +There are three keys corresponding to three types of pending operations: + +### `AFR_METADATA_PENDING` + +There are some metadata operations pending on this inode (perms, ctime/mtime, +xattr, etc.). + +### `AFR_DATA_PENDING` + +There is some data pending on this inode (writev). + +### `AFR_ENTRY_PENDING` + +There are some directory operations pending on this directory +(create, unlink, etc.). + +Self heal +--------- + +* On lookup, gather extended attribute data: + * If entry is a regular file: + * If an entry is present on one child and not on others: + * create entry on others. + * If entries exist but have different metadata (perms, etc.): + * consider the entry with the highest `AFR_METADATA_PENDING` number as + definitive and replicate its attributes on children. + * If entry is a directory: + * Consider the entry with the highest `AFR_ENTRY_PENDING` number as + definitive and replicate its contents on all children. + * If any two entries have non-matching types (i.e., one is file and + other is directory): + * Announce to the user via log that a split-brain situation has been + detected, and do nothing. +* On open, gather extended attribute data: + * Consider the file with the highest `AFR_DATA_PENDING` number as + the definitive one and replicate its contents on all other + children. + +During all self heal operations, appropriate locks must be held on all +regions/entries being affected. + +Inode scaling +------------- + +Inode scaling is necessary because if a situation arises where an inode number +is returned for a directory (by lookup) which was previously the inode number +of a file (as per FUSE's table), then FUSE gets horribly confused (consult a +FUSE expert for more details). + +To avoid such a situation, we distribute the 64-bit inode space equally +among all children of replicate. + +To illustrate: + +If c1, c2, c3 are children of replicate, they each get 1/3 of the available +inode space: + +------------- -- -- -- -- -- -- -- -- -- -- -- --- +Child: c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 ... +Inode number: 1 2 3 4 5 6 7 8 9 10 11 ... +------------- -- -- -- -- -- -- -- -- -- -- -- --- + +Thus, if lookup on c1 returns an inode number "2", it is scaled to "4" +(which is the second inode number in c1's space). + +This way we ensure that there is never a collision of inode numbers from +two different children. + +This reduction of inode space doesn't really reduce the usability of +replicate since even if we assume replicate has 1024 children (which would be a +highly unusual scenario), each child still has a 54-bit inode space: +$2^{54} \sim 1.8 \times 10^{16}$, which is much larger than any real +world requirement. diff --git a/doc/developer-guide/brickmux-thread-reduction.md b/doc/developer-guide/brickmux-thread-reduction.md new file mode 100644 index 00000000000..7d76e8ff579 --- /dev/null +++ b/doc/developer-guide/brickmux-thread-reduction.md @@ -0,0 +1,64 @@ +# Resource usage reduction in brick multiplexing + +Each brick is regresented with a graph of translators in a brick process. +Each translator in the graph has its own set of threads and mem pools +and other system resources allocations. Most of the times all these +resources are not put to full use. Reducing the resource consumption +of each brick is a problem in itself that needs to be addressed. The other +aspect to it is, sharing of resources across brick graph, this becomes +critical in brick multiplexing scenario. In this document we will be discussing +only about the threads. + +If a brick mux process hosts 50 bricks there are atleast 600+ threads created +in that process. Some of these are global threads that are shared by all the +brick graphs, and others are per translator threads. The global threads like +synctask threads, timer threads, sigwaiter, poller etc. are configurable and +do not needs to be reduced. The per translator threads keeps growing as the +number of bricks in the process increases. Each brick spawns atleast 10+ +threads: +- io-threads +- posix threads: + 1. Janitor + 2. Fsyncer + 3. Helper + 4. aio-thread +- changelog and bitrot threads(even when the features are not enabled) + +## io-threads + +io-threads should be made global to the process, having 16+ threads for +each brick does not make sense. But io-thread translator is loaded in +the graph, and the position of io-thread translator decides from when +the fops will be parallelised across threads. We cannot entirely move +the io-threads to libglusterfs and say the multiplexing happens from +the master translator or so. Hence, the io-thread orchestrator code +is moved to libglusterfs, which ensures there is only one set of +io-threads that is shared among the io-threads translator in each brick. +This poses performance issues due to lock-contention in the io-threds +layer. This also shall be addressed by having multiple locks instead of +one global lock for io-threads. + +## Posix threads +Most of the posix threads execute tasks in a timely manner, hence it can be +replaced with a timer whose handler register a task to synctask framework, once +the task is complete, the timer is registered again. With this we can eliminate +the need of one thread for each task. The problem with using synctasks is +the performance impact it will have due to make/swapcontext. For task that +does not involve network wait, we need not do makecontext, instead the task +function with arg can be stored and executed when a synctask thread is free. +We need to implement an api in synctask to execute atomic tasks(no network wait) +without the overhead of make/swapcontext. This will solve the performance +impact associated with using synctask framework. + +And the other challenge, is to cancel all the tasks pending from a translator. +This is important to cleanly detach brick. For this, we need to implement an +api in synctask that can cancel all the tasks from a given translator. + +For future, this will be replced to use global thread-pool(once implemented). + +## Changelog and bitrot threads + +In the initial implementation, the threads are not created if the feature is +not enabled. We need to share threads across changelog instances if we plan +to enable these features in brick mux scenario. + diff --git a/doc/developer-guide/coding-standard.md b/doc/developer-guide/coding-standard.md new file mode 100644 index 00000000000..031c6c0da99 --- /dev/null +++ b/doc/developer-guide/coding-standard.md @@ -0,0 +1,697 @@ +GlusterFS Coding Standards +========================== + +Before you get started +---------------------- +Before starting with other part of coding standard, install `clang-format` + +On Fedora: +``` +$ dnf install clang +``` +On debian/Ubuntu: +``` +$ apt-get install clang +``` +Once you are done with all the local changes, you need to run below set of commands, +before submitting the patch for review. +``` +$ git add $file # if any +$ git commit -a -s -m "commit message" +$ git show --pretty="format:" --name-only | grep -v "contrib/" | egrep "*\.[ch]$" | xargs clang-format -i +$ git diff # see if there are any changes +$ git commit -a --amend # get the format changes done +$ ./submit-for-review.sh +``` + + +Structure definitions should have a comment per member +------------------------------------------------------ + +Every member in a structure definition must have a comment about its purpose. +The comment should be descriptive without being overly verbose. For pointer +members, lifecycle concerns for the pointed-to object should be noted. For lock +members, the relationship between the lock member and the other members it +protects should be explicit. + +*Bad:* + +``` +gf_lock_t lock; /* lock */ +``` + +*Good:* + +``` +DBTYPE access_mode; /* access mode for accessing + * the databases, can be + * DB_HASH, DB_BTREE + * (option access-mode <mode>) + */ +``` + +Structure members should be aligned based on the padding requirements +--------------------------------------------------------------------- + +The compiler will make sure that structure members have optimum alignment, +but at the expense of suboptimal padding. More important is to optimize the +padding. The compiler won't do that for you. + +This also will help utilize the memory better + +*Bad:* +``` +struct bad { + bool b; /* 0 */ + /* 1..7 pad */ + void *p; /* 8..15 */ + char c; /* 16 */ + char a[16]; /* 17..33 */ + /* 34..39 pad */ + int64_t ii; /* 40..47 */ + int32_t i; /* 48..51 */ + /* 52..55 pad */ + int64_t iii; /* 56..63 */ +}; +``` + +*Good:* +``` +struct good { + int64_t ii; /* explicit 64-bit types */ + void *p; /* may be 64- or 32-bit */ + long l; /* may be 64- or 32-bit */ + int i; /* 32-bit */ + short s; /* 16-bit */ + char c; /* 8-bit */ + bool b; /* 8-bit */ + char a[1024]; +); +``` +Make sure the items with the most stringent alignment requirements will need +to come earliest (ie, pointers and perhaps uint64_t etc), and those with less +stringent alignment requirements at the end (uint16/uint8 and char). Also note +that the long array (if any) should be at the end of the structure, regardless +of the type. + +Also note, if your structure's overall size is crossing 1k-4k limit, it is +recommended to mention the reason why the particular structure needs so much +memory as a comment at the top. + +Use \_typename for struct tags and typename\_t for typedefs +--------------------------------------------------------- + +Being consistent here makes it possible to automate navigation from use of a +type to its true definition (not just the typedef). + +*Bad:* + +``` +struct thing {...}; +struct thing_t {...}; +typedef struct _thing thing; +``` + +*Good:* + +``` +typedef struct _thing {...} thing_t; +``` + +No double underscores +--------------------- + +Identifiers beginning with double underscores are supposed to reserved for the +compiler. + +http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf + +When you need to define inner/outer functions, use a different prefix/suffix. + +*Bad:* + +``` +void __do_something (void); + +void +do_something (void) +{ + LOCK (); + __do_something (); + UNLOCK (); +} +``` + +*Good:* + +``` +void do_something_locked (void); +``` + +Only use safe pointers in initializers +---------------------------------------------------------- + +Some pointers, such as `this` in a fop function, can be assumed to be non-NULL. +However, other parameters and further-derived values might be NULL. + +*Good:* + +``` +pid_t pid = frame->root->pid; +``` + + +*Bad:* + +``` +data_t *my_data = dict_get (xdata, "fubar"); +``` + +No giant stack allocations +-------------------------- + +Synctasks have small finite stacks. To avoid overflowing these stacks, avoid +allocating any large data structures on the stack. Use dynamic allocation +instead. + +*Bad:* + +``` +gf_boolean_t port_inuse[65536]; /* 256KB, this actually happened */ +``` + +NOTE: Ideal is to limit the stack array to less than 256 bytes. + + +Character array initializing +---------------------------- + +It is recommended to keep the character array initializing to empty string. + +*Good:* +``` +char msg[1024] = ""; +``` + +Not so much recommended, even though it means the same. + +``` +char msg[1024] = {0,}; +``` + +We recommend above to structure initialization. + + + +Validate all arguments to a function +------------------------------------ + +All pointer arguments to a function must be checked for `NULL`. +A macro named `GF_VALIDATE_OR_GOTO` (in `common-utils.h`) +takes two arguments; if the first is `NULL`, it writes a log message and +jumps to a label specified by the second aergument after setting errno +appropriately. There are several variants of this function for more +specific purposes, and their use is recommended. + +*Bad:* + +``` +/* top of function */ +ret = dict_get (xdata, ...) +``` + +*Good:* + +``` +/* top of function */ +GF_VALIDATE_OR_GOTO(xdata,out); +ret = dict_get (xdata, ...) +``` + +Never rely on precedence of operators +------------------------------------- + +Never write code that relies on the precedence of operators to execute +correctly. Such code can be hard to read and someone else might not +know the precedence of operators as accurately as you do. This includes +precedence of increment/decrement vs. field/subscript. The only exceptions are +arithmetic operators (which have had defined precedence since before computers +even existed) and boolean negation. + +*Bad:* + +``` +if (op_ret == -1 && errno != ENOENT) +++foo->bar /* incrementing foo, or incrementing foo->bar? */ +a && b || !c +``` + +*Good:* + +``` +if ((op_ret == -1) && (errno != ENOENT)) +(++foo)->bar +++(foo->bar) +(a && b) || !c +a && (b || !c) +``` + +Use exactly matching types +-------------------------- + +Use a variable of the exact type declared in the manual to hold the +return value of a function. Do not use an 'equivalent' type. + + +*Bad:* + +``` +int len = strlen (path); +``` + +*Good:* + +``` +size_t len = strlen (path); +``` + +Avoid code such as `foo->bar->baz`; check every pointer +------------------------------------------------------------- + +Do not write code that blindly follows a chain of pointer references. Any +pointer in the chain may be `NULL` and thus cause a crash. Verify that each +pointer is non-null before following it. Even if `foo->bar` has been checked +and is known safe, repeating it can make code more verbose and less clear. + +This rule includes `[]` as well as `->` because both dereference pointers. + +*Bad:* + +``` +foo->bar->field1 = value1; +xyz = foo->bar->field2 + foo->bar->field3 * foo->bar->field4; +foo->bar[5].baz +``` + +*Good:* + +``` +my_bar = foo->bar; +if (!my_bar) ... return; +my_bar->field1 = value1; +xyz = my_bar->field2 + my_bar->field3 * my_bar->field4; +``` + +Document unchecked return values +---------------------------------------------------- + +In general, return values should be checked. If a function is being called +for its side effects and the return value really doesn't matter, an explicit +cast to void is required (to keep static analyzers happy) and a comment is +recommended. + +*Bad:* + +``` +close (fd); +do_important_thing (); +``` + +*Good (or at least OK):* + +``` +(void) sleep (1); +``` + +Gracefully handle failure of malloc (and other allocation functions) +-------------------------------------------------------------------- + +GlusterFS should never crash or exit due to lack of memory. If a +memory allocation fails, the call should be unwound and an error +returned to the user. + +*Use result args and reserve the return value to indicate success or failure:* + +The return value of every functions must indicate success or failure (unless +it is impossible for the function to fail --- e.g., boolean functions). If +the function needs to return additional data, it must be returned using a +result (pointer) argument. + +*Bad:* + +``` +int32_t dict_get_int32 (dict_t *this, char *key); +``` + +*Good:* + +``` +int dict_get_int32 (dict_t *this, char *key, int32_t *val); +``` + +Always use the 'n' versions of string functions +----------------------------------------------- + +Unless impossible, use the length-limited versions of the string functions. + +*Bad:* + +``` +strcpy (entry_path, real_path); +``` + +*Good:* + +``` +strncpy (entry_path, real_path, entry_path_len); +``` + +Do not use memset prior to sprintf/snprintf/vsnprintf etc... +------------------------------------------------------------ +snprintf(and other similar string functions) terminates the buffer with a +'\0'(null character). Hence, there is no need to do a memset before using +snprintf. (Of course you need to account one extra byte for the null character +in your allocation). + +Note: Similarly if you are doing pre-memory allocation for the buffer, use +GF_MALLOC instead of GF_CALLOC, since the later is bit costlier. + +*Bad:* + +``` +char buffer[x]; +memset (buffer, 0, x); +bytes_read = snprintf (buffer, sizeof buffer, "bad standard"); +``` + +*Good:* +``` +char buffer[x]; +bytes_read = snprintf (buffer, sizeof (buffer), "good standard"); +``` + +And it is always to good initialize the char array if the string is static. + +E.g. +``` +char buffer[] = "good standard"; +``` + +No dead or commented code +------------------------- + +There must be no dead code (code to which control can never be passed) or +commented out code in the codebase. + +Function length or Keep functions small +--------------------------------------- + +We live in the UNIX-world where modules do one thing and do it well. +This rule should apply to our functions also. If a function is very long, try splitting it +into many little helper functions. The question is, in a coding +spree, how do we know a function is long and unreadable. One rule of +thumb given by Linus Torvalds is that, a function should be broken-up +if you have 4 or more levels of indentation going on for more than 3-4 +lines. + +*Example for a helper function:* +``` +static int +same_owner (posix_lock_t *l1, posix_lock_t *l2) +{ + return ((l1->client_pid == l2->client_pid) && + (l1->transport == l2->transport)); +} +``` + +Define functions as static +-------------------------- + +Declare functions as static unless they're exposed via a module-level API for +use from other modules. + +No nested functions +------------------- + +Nested functions have proven unreliable, e.g. as callbacks in code that uses +ucontext (green) threads, + +Use inline functions instead of macros whenever possible +-------------------------------------------------------- + +Inline functions enforce type safety; macros do not. Use macros only for things +that explicitly need to be type-agnostic (e.g. cases where one might use +generics or templates in other languages), or that use other preprocessor +features such as `#` for stringification or `##` for token pasting. In general, +"static inline" is the preferred form. + +Avoid copypasta +--------------- + +Code that is copied and then pasted into multiple functions often creates +maintenance problems later, e.g. updating all but one instance for a subsequent +change. If you find yourself copying the same "boilerplate" many places, +consider refactoring to use helper functions (including inline) or macros, or +code generation. + +Ensure function calls wrap around after 80-columns +-------------------------------------------------- + +Place remaining arguments on the next line if needed. + +Functions arguments and function definition +------------------------------------------- + +Place all the arguments of a function definition on the same line +until the line goes beyond 80-cols. Arguments that extend beyind +80-cols should be placed on the next line. + +Style issues +------------ + +### Brace placement + +Use K&R/Linux style of brace placement for blocks. + +*Good:* + +``` +int some_function (...) +{ + if (...) { + /* ... */ + } else if (...) { + /* ... */ + } else { + /* ... */ + } + + do { + /* ... */ + } while (cond); +} +``` + +### Indentation + +Use *eight* spaces for indenting blocks. Ensure that your +file contains only spaces and not tab characters. You can do this +in Emacs by selecting the entire file (`C-x h`) and +running `M-x untabify`. + +To make Emacs indent lines automatically by eight spaces, add this +line to your `.emacs`: + +``` +(add-hook 'c-mode-hook (lambda () (c-set-style "linux"))) +``` + +### Comments + +Write a comment before every function describing its purpose (one-line), +its arguments, and its return value. Mention whether it is an internal +function or an exported function. + +Write a comment before every structure describing its purpose, and +write comments about each of its members. + +Follow the style shown below for comments, since such comments +can then be automatically extracted by doxygen to generate +documentation. + +*Good:* + +``` +/** +* hash_name -hash function for filenames +* @par: parent inode number +* @name: basename of inode +* @mod: number of buckets in the hashtable +* +* @return: success: bucket number +* failure: -1 +* +* Not for external use. +*/ +``` + +### Indicating critical sections + +To clearly show regions of code which execute with locks held, use +the following format: + +``` +pthread_mutex_lock (&mutex); +{ + /* code */ +} +pthread_mutex_unlock (&mutex); +``` + +### Always use braces + +Even around single statements. + +*Bad:* + +``` +if (condition) action (); + +if (condition) + action (); +``` + +*Good:* + +``` +if (condition) { + action (); +} +``` + +### Avoid multi-line conditionals + +These can be hard to read and even harder to modify later. Predicate functions +and helper variables are always better for maintainability. + +*Bad:* + +``` +if ((thing1 && other_complex_condition (thing1, lots, of, args)) + || (!thing2 || even_more_complex_condition (thing2)) + || all_sorts_of_stuff_with_thing3) { + return; +} + +``` + +*Better:* + +``` +thing1_ok = predicate1 (thing1, lots, of, args +thing2_ok = predicate2 (thing2); +thing3_ok = predicate3 (thing3); + +if (!thing1_ok || !thing2_ok || !thing3_ok) { + return; +} +``` + +*Best:* + +``` +if (thing1 && other_complex_condition (thing1, lots, of, args)) { + return; +} +if (!thing2 || even_more_complex_condition (thing2)) { + /* Note potential for a different message here. */ + return; +} +if (all_sorts_of_stuff_with_thing3) { + /* And here too. */ + return; +} +``` + +### Use 'const' liberally + +If a value isn't supposed/expected to change, there's no cost to adding a +'const' keyword and it will help prevent violation of expectations. + +### Avoid global variables (including 'static' auto variables) +Almost all state in Gluster is contextual and should be contained in the +appropriate structure reflecting its scope (e.g. `call\_frame\_t`, `call\_stack\_t`, +`xlator\_t`, `glusterfs\_ctx\_t`). With dynamic loading and graph switches in play, +each global requires careful consideration of when it should be initialized or +reinitialized, when it might _accidentally_ be reinitialized, when its value +might become stale, and so on. A few global variables are needed to serve as +'anchor points' for these structures, and more exceptions to the rule might be +approved in the future, but new globals should not be added to the codebase +without explicit approval. + +## A skeleton fop function + +This is the recommended template for any fop. In the beginning come the +initializations. After that, the 'success' control flow should be linear. Any +error conditions should cause a `goto` to a label at the end. By convention +this is 'out' if there is only one such label, but a cascade of such labels is +allowable to support multi-stage cleanup. At that point, the code should detect +the error that has occurred and do appropriate cleanup. + +``` +int32_t +sample_fop (call_frame_t *frame, xlator_t *this, ...) +{ + char * var1 = NULL; + int32_t op_ret = -1; + int32_t op_errno = 0; + DIR * dir = NULL; + struct posix_fd * pfd = NULL; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (this, out); + + /* other validations */ + + dir = opendir (...); + + if (dir == NULL) { + op_errno = errno; + gf_log (this->name, GF_LOG_ERROR, + "opendir failed on %s (%s)", loc->path, + strerror (op_errno)); + goto out; + } + + /* another system call */ + if (...) { + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "out of memory :("); + goto out; + } + + /* ... */ + + out: + if (op_ret == -1) { + + /* check for all the cleanup that needs to be + done */ + + if (dir) { + closedir (dir); + dir = NULL; + } + + if (pfd) { + FREE (pfd->path); + FREE (pfd); + pfd = NULL; + } + } + + STACK_UNWIND (frame, op_ret, op_errno, fd); + return 0; +} +``` diff --git a/doc/developer-guide/commit-guidelines.md b/doc/developer-guide/commit-guidelines.md new file mode 100644 index 00000000000..38bbe525cbd --- /dev/null +++ b/doc/developer-guide/commit-guidelines.md @@ -0,0 +1,136 @@ +## Git Commit Good Practice + +The following document is based on experience doing code development, bug troubleshooting and code review across a number of projects using Git. The document is mostly borrowed from [Open Stack](https://wiki.openstack.org/wiki/GitCommitMessages), but made more meaningful in the context of GlusterFS project. + +This topic can be split into two areas of concern + +* The structured set/split of the code changes +* The information provided in the commit message + +### Executive Summary +The points and examples that will be raised in this document ought to clearly demonstrate the value in splitting up changes into a sequence of individual commits, and the importance in writing good commit messages to go along with them. If these guidelines were widely applied it would result in a significant improvement in the quality of the GlusterFS Git history. Both a carrot & stick will be required to effect changes. This document intends to be the carrot by alerting people to the benefits, while anyone doing Gerrit code review can act as the stick ;-P + +In other words, when reviewing a change in Gerrit: +* Do not simply look at the correctness of the code. +* Review the commit message itself and request improvements to its content. +* Look out for commits which are mixing multiple logical changes and require the submitter to split them into separate commits. +* Ensure whitespace changes are not mixed in with functional changes. +* Ensure no-op code refactoring is done separately from functional changes. + +And so on. + +It might be mentioned that Gerrit's handling of patch series is not entirely perfect. Let that not become a valid reason to avoid creating patch series. The tools being used should be subservient to developers needs, and since they are open source they can be fixed / improved. Software source code is "read mostly, write occassionally" and thus the most important criteria is to improve the long term maintainability by the large pool of developers in the community, and not to sacrifice too much for the sake of the single author who may never touch the code again. + +And now the long detailed guidelines & examples of good & bad practice + +### Structural split of changes +The cardinal rule for creating good commits is to ensure there is only one "logical change" per commit. There are many reasons why this is an important rule: + +* The smaller the amount of code being changed, the quicker & easier it is to review & identify potential flaws. +* If a change is found to be flawed later, it may be necessary to revert the broken commit. This is much easier to do if there are not other unrelated code changes entangled with the original commit. +* When troubleshooting problems using Git's bisect capability, small well defined changes will aid in isolating exactly where the code problem was introduced. +* When browsing history using Git annotate/blame, small well defined changes also aid in isolating exactly where & why a piece of code came from. + +#### Things to avoid when creating commits +With the above points in mind, there are some commonly encountered examples of bad things to avoid + +* Mixing whitespace changes with functional code changes. + +The whitespace changes will obscure the important functional changes, making it harder for a reviewer to correctly determine whether the change is correct. Solution: Create 2 commits, one with the whitespace changes, one with the functional changes. Typically the whitespace change would be done first, but that need not be a hard rule. + +* Mixing two unrelated functional changes. + +Again the reviewer will find it harder to identify flaws if two unrelated changes are mixed together. If it becomes necessary to later revert a broken commit, the two unrelated changes will need to be untangled, with further risk of bug creation. + +* Sending large new features in a single giant commit. + +It may well be the case that the code for a new feature is only useful when all of it is present. This does not, however, imply that the entire feature should be provided in a single commit. New features often entail refactoring existing code. It is highly desirable that any refactoring is done in commits which are separate from those implementing the new feature. This helps reviewers and test suites validate that the refactoring has no unintentional functional changes. + +Even the newly written code can often be split up into multiple pieces that can be independently reviewed. For example, changes which add new internal fops or library functions, can be in self-contained commits. Again this leads to easier code review. It also allows other developers to cherry-pick small parts of the work, if the entire new feature is not immediately ready for merge. This will encourage the author & reviewers to think about the generic library functions' design, and not simply pick a design that is easier for their currently chosen internal implementation. + +The basic rule to follow is + +If a code change can be split into a sequence of patches/commits, then it should be split. Less is not more. More is more. + +##### Examples of bad practice + +TODO: Pick glusterfs specific example. + + +##### Examples of good practice + + +### Information in commit messages +As important as the content of the change, is the content of the commit message describing it. When writing a commit message there are some important things to remember + +* Do not assume the reviewer understands what the original problem was. + +When reading bug reports, after a number of back & forth comments, it is often as clear as mud, what the root cause problem is. The commit message should have a clear statement as to what the original problem is. The bug is merely interesting historical background on /how/ the problem was identified. It should be possible to review a proposed patch for correctness without needing to read the bug ticket. + +* Do not assume the reviewer has access to external web services/site. + +In 6 months time when someone is on a train/plane/coach/beach/pub troubleshooting a problem & browsing Git history, there is no guarantee they will have access to the online bug tracker, or online blueprint documents. The great step forward with distributed SCM is that you no longer need to be "online" to have access to all information about the code repository. The commit message should be totally self-contained, to maintain that benefit. + +* Do not assume the code is self-evident/self-documenting. + +What is self-evident to one person, might be clear as mud to another person. Always document what the original problem was and how it is being fixed, for any change except the most obvious typos, or whitespace only commits. + +* Describe why a change is being made. + +A common mistake is to just document how the code has been written, without describing /why/ the developer chose to do it that way. By all means describe the overall code structure, particularly for large changes, but more importantly describe the intent/motivation behind the changes. + +* Read the commit message to see if it hints at improved code structure. + +Often when describing a large commit message, it becomes obvious that a commit should have in fact been split into 2 or more parts. Don't be afraid to go back and rebase the change to split it up into separate commits. + +* Ensure sufficient information to decide whether to review. + +When Gerrit sends out email alerts for new patch submissions there is minimal information included, principally the commit message and the list of files changes. Given the high volume of patches, it is not reasonable to expect all reviewers to examine the patches in detail. The commit message must thus contain sufficient information to alert the potential reviewers to the fact that this is a patch they need to look at. + +* The first commit line is the most important. + +In Git commits the first line of the commit message has special significance. It is used as email subject line, git annotate messages, gitk viewer annotations, merge commit messages and many more places where space is at a premium. As well as summarizing the change itself, it should take care to detail what part of the code is affected. eg if it is 'afr', 'dht' or any translator. Or in some cases, it can be touching all these components, but the commit message can be 'coverity:', 'txn-framework:', 'new-fop: ', etc. + +* Describe any limitations of the current code. + +If the code being changed still has future scope for improvements, or any known limitations then mention these in the commit message. This demonstrates to the reviewer that the broader picture has been considered and what tradeoffs have been done in terms of short term goals vs. long term wishes. + +* Do not include patch set-specific comments. + +In other words, if you rebase your change please don't add "Patch set 2: rebased" to your commit message. That isn't going to be relevant once your change has merged. Please do make a note of that in Gerrit as a comment on your change, however. It helps reviewers know what changed between patch sets. This also applies to comments such as "Added unit tests", "Fixed localization problems", or any other such patch set to patch set changes that don't affect the overall intent of your commit. + +**The main rule to follow is:** + +The commit message must contain all the information required to fully understand & review the patch for correctness. Less is not more. More is more. + + +#### Including external references + +The commit message is primarily targeted towards human interpretation, but there is always some metadata provided for machine use. In the case of GlusterFS this includes at least the 'Change-id', "bug"/"feature" ID references and "Signed-off-by" tag (generated by 'git commit -s'). + +The 'Change-id' line is a unique hash describing the change, which is generated by a Git commit hook. This should not be changed when rebasing a commit following review feedback, since it is used by Gerrit, to track versions of a patch. + +The 'bug' line can reference a bug in a few ways. Gerrit creates a link to the bug when viewing the patch on review.gluster.org so that reviewers can quickly access the bug/issue on Bugzilla or Github. + +**Fixes: bz#1601166** -- use 'Fixes: bz#NNNNN' if the commit is intended to fully fix and close the bug being referenced. +**Fixes: #411** -- use 'Fixes: #NNN' if the patch fixes the github issue completely. + +**Updates: bz#1193929** -- use 'Updates: bz#NNNN' if the commit is only a partial fix and more work is needed. +**Updates: #175** -- use 'Updates: #NNNN' if the commit is only a partial fix and more work is needed for the feature completion. + +We encourage the use of `Co-Authored-By: name <name@example.com>` in commit messages to indicate people who worked on a particular patch. It's a convention for recognizing multiple authors, and our projects would encourage the stats tools to observe it when collecting statistics. + +### Summary of Git commit message structure + +* Provide a brief description of the change in the first line. +* The first line should be limited to 50 characters and should not end with a period. + +* Insert a single blank line after the first line. + +* Provide a detailed description of the change in the following lines, breaking paragraphs where needed. + +* Subsequent lines should be wrapped at 72 characters. + +Put the 'Change-id', 'Fixes bz#NNNNN' and 'Signed-off-by: <>' lines at the very end. + +TODO: Add good examples diff --git a/doc/developer-guide/daemon-management-framework.md b/doc/developer-guide/daemon-management-framework.md new file mode 100644 index 00000000000..592192e665d --- /dev/null +++ b/doc/developer-guide/daemon-management-framework.md @@ -0,0 +1,38 @@ + +How to introduce new daemons using daemon management framework +============================================================== +Glusterd manages GlusterFS daemons providing services like NFS, Proactive +self-heal, Quota, User servicable snapshots etc. Following are some of the +aspects that come under daemon management. + +Data members & functions of different management objects + +- **Connection Management** + - unix domain sockets based channel for internal communication + - rpc connection for the communication + - frame timeout value for UDS + - Methods - notify + - init, connect, termination, disconnect APIs can be invoked using the + connection management object + +- **Process Management** + - Name of the process + - pidfile to detect if the daemon is running + - loggging directory, log file, volfile, volfileserver & volfileid + - init, stop APIs can be invoked using the process management object + +- **Service Management** + - connection object + - process object + - online status + - Methods - manager, start, stop which can be abstracted as a common methods + or specific to service requirements + - init API can be invoked using the service management object + + The above structures defines the skeleton of the daemon management framework. + Introduction of new daemons in GlusterFS needs to inherit these properties. Any + requirement specific to a daemon needs to be implemented in its own service + (for eg : snapd defines its own type glusterd_snapdsvc_t using glusterd_svc_t + and snapd specific data). New daemons will need to have its own service specific + code written in glusterd-<feature>-svc.h{c} and need to reuse the existing + framework. diff --git a/doc/developer-guide/datastructure-inode.md b/doc/developer-guide/datastructure-inode.md new file mode 100644 index 00000000000..45d7a941e5f --- /dev/null +++ b/doc/developer-guide/datastructure-inode.md @@ -0,0 +1,221 @@ +# Inode and dentry management in GlusterFS: + +## Background +Filesystems internally refer to files and directories via inodes. Inodes +are unique identifiers of the entities stored in a filesystem. Whenever an +application has to operate on a file/directory (read/modify), the filesystem +maps that file/directory to the right inode and start referring to that inode +whenever an operation has to be performed on the file/directory. + +In GlusterFS a new inode gets created whenever a new file/directory is created +OR when a successful lookup is done on a file/directory for the first time. +Inodes in GlusterFS are maintained by the inode table which gets initiated when +the filesystem daemon is started (both for the brick process as well as the +mount process). Below are some important data structures for inode management. + +## Data-structure (inode-table) +``` +struct _inode_table { + pthread_mutex_t lock; + size_t hashsize; /* bucket size of inode hash and dentry hash */ + char *name; /* name of the inode table, just for gf_log() */ + inode_t *root; /* root directory inode, with inode + number and gfid 1 */ + xlator_t *xl; /* xlator to be called to do purge and + the xlator which maintains the inode table*/ + uint32_t lru_limit; /* maximum LRU cache size */ + struct list_head *inode_hash; /* buckets for inode hash table */ + struct list_head *name_hash; /* buckets for dentry hash table */ + struct list_head active; /* list of inodes currently active (in an fop) */ + uint32_t active_size; /* count of inodes in active list */ + struct list_head lru; /* list of inodes recently used. + lru.next most recent */ + uint32_t lru_size; /* count of inodes in lru list */ + struct list_head purge; /* list of inodes to be purged soon */ + uint32_t purge_size; /* count of inodes in purge list */ + + struct mem_pool *inode_pool; /* memory pool for inodes */ + struct mem_pool *dentry_pool; /* memory pool for dentrys */ + struct mem_pool *fd_mem_pool; /* memory pool for fd_t */ + int ctxcount; /* number of slots in inode->ctx */ +}; +``` + +# Life-cycle +``` +inode_table_new (size_t lru_limit, xlator_t *xl) +``` +This is a function which allocates a new inode table. Usually the top xlators in +the graph such as protocol/server (for bricks), fuse and nfs (for fuse and nfs +mounts) and libgfapi do inode managements. Hence they are the ones which will +allocate a new inode table by calling the above function. + +Each xlator graph in glusterfs maintains an inode table. So in fuse clients, +whenever there is a graph change due to add brick/remove brick or +addition/removal of some other xlators, a new graph is created which creates a +new inode table. + +Thus an allocated inode table is destroyed only when the filesystem daemon is +killed or unmounted. + + +# what it contains. +Inode table in glusterfs mainly contains a hash table for maintaining inodes. +In general a file/directory is considered to be existing if there is a +corresponding inode present in the inode table. If a inode for a file/directory +cannot be found in the inode table, glusterfs tries to resolve it by sending a +lookup on the entry for which the inode is needed. If lookup is successful, then +a new inode correponding to the entry is added to the hash table present in the +inode table. Thus an inode present in the hash-table means, its an existing +file/directory within the filesystem. The inode table also contains the hash +size of the hash table (as of now it is hard coded to 14057. The hash value of +a inode is calculated using its gfid). + +Apart from the hash table, inode table also maintains 3 important list of inodes +1. Active list: +Active list contains all the active inodes (i.e inodes which are currently part +of some fop). +2. Lru list: +Least recently used inodes list. A limit can be set for the size of the lru +list. For bricks it is 16384 and for clients it is infinity. +3. Purge list: +List of all the inodes which have to be purged (i.e inodes which have to be +deleted from the inode table due to unlink/rmdir/forget). + +And at last it also contains the mem-pool for allocating inodes, dentries so +that frequent malloc/calloc and free of the data structures can be avoided. + + +# Data structure (inode) +``` +struct _inode { + inode_table_t *table; /* the table this inode belongs to */ + uuid_t gfid; /* unique identifier of the inode */ + gf_lock_t lock; + uint64_t nlookup; + uint32_t fd_count; /* Open fd count */ + uint32_t ref; /* reference count on this inode */ + ia_type_t ia_type; /* what kind of file */ + struct list_head fd_list; /* list of open files on this inode */ + struct list_head dentry_list; /* list of directory entries for this inode */ + struct list_head hash; /* hash table pointers */ + struct list_head list; /* active/lru/purge */ + + struct _inode_ctx *_ctx; /* place holder for keeping the + information about the inode by different xlators */ +}; +``` +As said above, inodes are internal way of identifying the files/directories. A +inode uniquely represents a file/directory. A new inode is created whenever a +create/mkdir/symlink/mknod operations are performed. Apart from that a new inode +is created upon the successful fresh lookup of a file/directory. Say the +filesystem contained some file "a" within root and the filesystem was +unmounted. Now when glusterfs is mounted and some operation is perfomed on "/a", +glusterfs tries to get the inode for the entry "a" with parent inode as +root. But, since glusterfs just came up, it will not be able to find the inode +for "a" and will send a lookup on "/a". If the lookup operation succeeds (i.e. +the root of glusterfs contains an entry called "a"), then a new inode for "/a" +is created and added to the inode table. + +Depending upon the situation, an inode can be in one of the 3 lists maintained +by the inode table. If some fop is happening on the inode, then the inode will +be present in the active inodes list maintained by the inode table. Active +inodes are those inodes whose refcount is greater than zero. Whenever some +operation comes on a file/directory, and the resolver tries to find the inode +for it, it increments the refcount of the inode before returning the inode. The +refcount of an inode can be incremented by calling the below function +``` +inode_ref (inode_t *inode) +``` +Any xlator which wants to operate on a inode as part of some fop (or wants the +inode in the callback), should hold a ref on the inode. +Once the fop is completed before sending the reply of the fop to the above +layers , the inode has to be unrefed. When the refcount of an inode becomes +zero, it is removed from the active inodes list and put into LRU list maintained +by the inode table. Thus in short if some fop is happening on a file/directory, +the corresponding inode will be in the active list or it will be in the LRU +list. + + +# Life Cycle + +A new inode is created whenever a new file/directory/symlink is created OR a +successful lookup of an existing entry is done. The xlators which does inode +management (as of now protocol/server, fuse, nfs, gfapi) will perform inode_link +operation upon successful lookup or successful creation of a new entry. +``` +inode_link (inode_t *inode, inode_t *parent, const char *name, + struct iatt *buf); +``` +inode_link actually adds the inode to the inode table (to be precise it adds +the inode to the hash table maintained by the inode table. The hash value is +calculated based on the gfid). Copies the gfid to the inode (the gfid is +present in the iatt structure). Creates a dentry with the new name. + +A inode is removed from the inode table and eventually destroyed when unlink +or rmdir operation is performed on a file/directory, or the the lru limit of +the inode table has been exceeded. + +# Data structure (dentry) +``` + +struct _dentry { + struct list_head inode_list; /* list of dentries of inode */ + struct list_head hash; /* hash table pointers */ + inode_t *inode; /* inode of this directory entry */ + char *name; /* name of the directory entry */ + inode_t *parent; /* directory of the entry */ +}; +``` +A dentry is the presence of an entry for a file/directory within its parent +directory. A dentry usually points to the inode to which it belongs to. In +glusterfs a dentry contains the following fields. +1. a hook using which it can add itself to the list of +the dentries maintained by the inode to which it points to. +2. A hash table pointer. +3. Pointer to the inode to which it belongs to. +4. Name of the dentry +5. Pointer to the inode of the parent directory in which the dentry is present + +A new dentry is created when a new file/directory/symlink is created or a hard +link to an existing file is created. +``` +__dentry_create (inode_t *inode, inode_t *parent, const char *name); +``` +A dentry holds a refcount on the parent +directory so that the parent inode is never removed from the active inode's list +and put to the lru list (If the lru limit of the lru list is exceeded, there is +a chance of parent inode being destroyed. To avoid it, the dentries hold a +reference to the parent inode). A dentry is removed whenevern a unlink/rmdir +is perfomed on a file/directory. Or when the lru limit has been exceeded, the +oldest inodes are purged out of the inode table, during which all the dentries +of the inode are removed. + +Whenever a unlink/rmdir comes on a file/directory, the corresponding inode +should be removed from the inode table. So upon unlink/rmdir, the inode will +be moved to the purge list maintained by the inode table and from there it is +destroyed. To be more specific, if a inode has to be destroyed, its refcount +and nlookup count both should become 0. For refcount to become 0, the inode +should not be part of any fop (there should not be any open fds). Or if the +inode belongs to a directory, then there should not be any fop happening on the +directory and it should not contain any dentries within it. For nlookup count to +become zero, a forget has to be sent on the inode with nlookup count set to 0 as +an argument. For fuse clients, forget is sent by the kernel itself whenever a +unlink/rmdir is performed. But for brick processes, upon unlink/rmdir, the +protocol/server itself has to do inode_forget. Whenever the inode has to be +deleted due to file removal or lru limit being exceeded the inode is retired +(i.e. all the dentries of the inode are deleted and the inode is moved to the +purge list maintained by the inode table), the nlookup count is set to 0 via +inode_forget api. The inode table, then prunes all the inodes from the purge +list by destroying the inode contexts maintained by each xlator. +``` +unlinking of the dentry is done via inode_unlink; + +void +inode_unlink (inode_t *inode, inode_t *parent, const char *name); +``` +If the inode has multiple hard links, then the unlink operation performed by +the application results just in the removal of the dentry with the name provided +by the application. For the inode to be removed, all the dentries of the inode +should be unlinked. + diff --git a/doc/developer-guide/datastructure-iobuf.md b/doc/developer-guide/datastructure-iobuf.md new file mode 100644 index 00000000000..03604e3672c --- /dev/null +++ b/doc/developer-guide/datastructure-iobuf.md @@ -0,0 +1,259 @@ +# Iobuf-pool +## Datastructures +### iobuf +Short for IO Buffer. It is one allocatable unit for the consumers of the IOBUF +API, each unit hosts @page_size(defined in arena structure) bytes of memory. As +initial step of processing a fop, the IO buffer passed onto GlusterFS by the +other applications (FUSE VFS/ Applications using gfapi) is copied into GlusterFS +space i.e. iobufs. Hence Iobufs are mostly allocated/deallocated in Fuse, gfapi, +protocol xlators, and also in performance xlators to cache the IO buffers etc. +``` +struct iobuf { + union { + struct list_head list; + struct { + struct iobuf *next; + struct iobuf *prev; + }; + }; + struct iobuf_arena *iobuf_arena; + + gf_lock_t lock; /* for ->ptr and ->ref */ + int ref; /* 0 == passive, >0 == active */ + + void *ptr; /* usable memory region by the consumer */ + + void *free_ptr; /* in case of stdalloc, this is the + one to be freed not the *ptr */ +}; +``` + +### iobref +There may be need of multiple iobufs for a single fop, like in vectored read/write. +Hence multiple iobufs(default 16) are encapsulated under one iobref. +``` +struct iobref { + gf_lock_t lock; + int ref; + struct iobuf **iobrefs; /* list of iobufs */ + int alloced; /* 16 by default, grows as required */ + int used; /* number of iobufs added to this iobref */ +}; +``` +### iobuf_arenas +One region of memory MMAPed from the operating system. Each region MMAPs +@arena_size bytes of memory, and hosts @arena_size / @page_size IOBUFs. +The same sized iobufs are grouped into one arena, for sanity of access. + +``` +struct iobuf_arena { + union { + struct list_head list; + struct { + struct iobuf_arena *next; + struct iobuf_arena *prev; + }; + }; + + size_t page_size; /* size of all iobufs in this arena */ + size_t arena_size; /* this is equal to + (iobuf_pool->arena_size / page_size) + * page_size */ + size_t page_count; + + struct iobuf_pool *iobuf_pool; + + void *mem_base; + struct iobuf *iobufs; /* allocated iobufs list */ + + int active_cnt; + struct iobuf active; /* head node iobuf + (unused by itself) */ + int passive_cnt; + struct iobuf passive; /* head node iobuf + (unused by itself) */ + uint64_t alloc_cnt; /* total allocs in this pool */ + int max_active; /* max active buffers at a given time */ +}; + +``` +### iobuf_pool +Pool of Iobufs. As there may be many Io buffers required by the filesystem, +a pool of iobufs are preallocated and kept, if these preallocated ones are +exhausted only then the standard malloc/free is called, thus improving the +performance. Iobuf pool is generally one per process, allocated during +glusterfs_ctx_t init (glusterfs_ctx_defaults_init), currently the preallocated +iobuf pool memory is freed on process exit. Iobuf pool is globally accessible +across GlusterFs, hence iobufs allocated by any xlator can be accessed by any +other xlators(unless iobuf is not passed). +``` +struct iobuf_pool { + pthread_mutex_t mutex; + size_t arena_size; /* size of memory region in + arena */ + size_t default_page_size; /* default size of iobuf */ + + int arena_cnt; + struct list_head arenas[GF_VARIABLE_IOBUF_COUNT]; + /* array of arenas. Each element of the array is a list of arenas + holding iobufs of particular page_size */ + + struct list_head filled[GF_VARIABLE_IOBUF_COUNT]; + /* array of arenas without free iobufs */ + + struct list_head purge[GF_VARIABLE_IOBUF_COUNT]; + /* array of of arenas which can be purged */ + + uint64_t request_misses; /* mostly the requests for higher + value of iobufs */ +}; +``` +~~~ +The default size of the iobuf_pool(as of yet): +1024 iobufs of 128Bytes = 128KB +512 iobufs of 512Bytes = 256KB +512 iobufs of 2KB = 1MB +128 iobufs of 8KB = 1MB +64 iobufs of 32KB = 2MB +32 iobufs of 128KB = 4MB +8 iobufs of 256KB = 2MB +2 iobufs of 1MB = 2MB +Total ~13MB +~~~ +As seen in the datastructure iobuf_pool has 3 arena lists. + +- arenas: +The arenas allocated during iobuf_pool create, are part of this list. This list +also contains arenas that are partially filled i.e. contain few active and few +passive iobufs (passive_cnt !=0, active_cnt!=0 except for initially allocated +arenas). There will be by default 8 arenas of the sizes mentioned above. +- filled: +If all the iobufs in the arena are filled(passive_cnt = 0), the arena is moved +to the filled list. If any of the iobufs from the filled arena is iobuf_put, +then the arena moves back to the 'arenas' list. +- purge: +If there are no active iobufs in the arena(active_cnt = 0), the arena is moved +to purge list. iobuf_put() triggers destruction of the arenas in this list. The +arenas in the purge list are destroyed only if there is atleast one arena in +'arenas' list, that way there won't be spurious mmap/unmap of buffers. +(e.g: If there is an arena (page_size=128KB, count=32) in purge list, this arena +is destroyed(munmap) only if there is an arena in 'arenas' list with page_size=128KB). + +## APIs +### iobuf_get + +``` +struct iobuf *iobuf_get (struct iobuf_pool *iobuf_pool); +``` +Creates a new iobuf of the default page size(128KB hard coded as of yet). +Also takes a reference(increments ref count), hence no need of doing it +explicitly after getting iobuf. + +### iobuf_get2 + +``` +struct iobuf * iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size); +``` +Creates a new iobuf of a specified page size, if page_size=0 default page size +is considered. +``` +if (requested iobuf size > Max iobuf size in the pool(1MB as of yet)) + { + Perform standard allocation(CALLOC) of the requested size and + add it to the list iobuf_pool->arenas[IOBUF_ARENA_MAX_INDEX]. + } + else + { + -Round the page size to match the stndard sizes in iobuf pool. + (eg: if 3KB is requested, it is rounded to 8KB). + -Select the arena list corresponding to the rounded size + (eg: select 8KB arena) + If the selected arena has passive count > 0, then return the + iobuf from this arena, set the counters(passive/active/etc.) + appropriately. + else the arena is full, allocate new arena with rounded size + and standard page numbers and add to the arena list + (eg: 128 iobufs of 8KB is allocated). + } +``` +Also takes a reference(increments ref count), hence no need of doing it +explicitly after getting iobuf. + +### iobuf_ref + +``` +struct iobuf *iobuf_ref (struct iobuf *iobuf); +``` + Take a reference on the iobuf. If using an iobuf allocated by some other +xlator/function/, its a good practice to take a reference so that iobuf is not +deleted by the allocator. + +### iobuf_unref +``` +void iobuf_unref (struct iobuf *iobuf); +``` +Unreference the iobuf, if the ref count is zero iobuf is considered free. + +``` + -Delete the iobuf, if allocated from standard alloc and return. + -set the active/passive count appropriately. + -if passive count > 0 then add the arena to 'arena' list. + -if active count = 0 then add the arena to 'purge' list. +``` +Every iobuf_ref should have a corresponding iobuf_unref, and also every +iobuf_get/2 should have a correspondning iobuf_unref. + +### iobref_new +``` +struct iobref *iobref_new (); +``` +Creates a new iobref structure and returns its pointer. + +### iobref_ref +``` +struct iobref *iobref_ref (struct iobref *iobref); +``` +Take a reference on the iobref. + +### iobref_unref +``` +void iobref_unref (struct iobref *iobref); +``` +Decrements the reference count of the iobref. If the ref count is 0, then unref +all the iobufs(iobuf_unref) in the iobref, and destroy the iobref. + +### iobref_add +``` +int iobref_add (struct iobref *iobref, struct iobuf *iobuf); +``` +Adds the given iobuf into the iobref, it takes a ref on the iobuf before adding +it, hence explicit iobuf_ref is not required if adding to the iobref. + +### iobref_merge +``` +int iobref_merge (struct iobref *to, struct iobref *from); +``` +Adds all the iobufs in the 'from' iobref to the 'to' iobref. Merge will not +cause the delete of the 'from' iobref, therefore it will result in another ref +on all the iobufs added to the 'to' iobref. Hence iobref_unref should be +performed both on 'from' and 'to' iobrefs (performing iobref_unref only on 'to' +will not free the iobufs and may result in leak). + +### iobref_clear +``` +void iobref_clear (struct iobref *iobref); +``` +Unreference all the iobufs in the iobref, and also unref the iobref. + +## Iobuf Leaks +If all iobuf_refs/iobuf_new do not have correspondning iobuf_unref, then the +iobufs are not freed and recurring execution of such code path may lead to huge +memory leaks. The easiest way to identify if a memory leak is caused by iobufs +is to take a statedump. If the statedump shows a lot of filled arenas then it is +a sure sign of leak. Refer doc/debugging/statedump.md for more details. + +If iobufs are leaking, the next step is to find where the iobuf_unref went +missing. There is no standard/easy way of debugging this, code reading and logs +are the only ways. If there is a liberty to reproduce the memory leak at will, +then logs(gf_callinginfo) in iobuf_ref/unref might help. +TODO: A easier way to debug iobuf leaks. diff --git a/doc/developer-guide/datastructure-mem-pool.md b/doc/developer-guide/datastructure-mem-pool.md new file mode 100644 index 00000000000..225567cbf9f --- /dev/null +++ b/doc/developer-guide/datastructure-mem-pool.md @@ -0,0 +1,124 @@ +# Mem-pool +## Background +There was a time when every fop in glusterfs used to incur cost of allocations/de-allocations for every stack wind/unwind between xlators because stack/frame/*_localt_t in every wind/unwind was allocated and de-allocated. Because of all these system calls in the fop path there was lot of latency and the worst part is that most of the times the number of frames/stacks active at any time wouldn't cross a threshold. So it was decided that this threshold number of frames/stacks would be allocated in the beginning of the process only once. Get one of them from the pool of stacks/frames whenever `STACK_WIND` is performed and put it back into the pool in `STACK_UNWIND`/`STACK_DESTROY` without incurring any extra system calls. The data structures are allocated only when threshold number of such items are in active use i.e. pool is in complete use.% increase in the performance once this was added to all the common data structures (inode/fd/dict etc) in xlators throughout the stack was tremendous. + +## Data structure +``` +struct mem_pool { + struct list_head list; /*Each member in the mempool is element padded with a doubly-linked-list + ptr of mempool + is-in +-use info. This list is used to add the element to the list of free members in the mem-pool*/ + int hot_count;/*number of mempool elements that are in active use*/ + int cold_count;/*number of mempool elements that are not in use. If a new allocation is required it +will be served from here until all the elements in the pool are in use i.e. cold-count becomes 0.*/ + gf_lock_t lock;/*synchronization mechanism*/ + unsigned long padded_sizeof_type;/*Each mempool element is padded with a doubly-linked-list + ptr of mempool + is-in +-use info to operate the pool of elements, this size is the element-size after padding*/ + void *pool;/*Starting address of pool*/ + void *pool_end;/*Ending address of pool*/ +/* If an element address is in the range between pool, pool_end addresses then it is alloced from the pool otherwise it is 'calloced' this is very useful for functions like 'mem_put'*/ + int real_sizeof_type;/* size of just the element without any padding*/ + uint64_t alloc_count; /*Number of times this type of data is allocated through out the life of this process. This may include calloced elements as well*/ + uint64_t pool_misses; /*Number of times the element had to be allocated from heap because all elements from the pool are in active use.*/ + int max_alloc; /*Maximum number of elements from the pool in active use at any point in the life of the process. This does *not* include calloced elements*/ + int curr_stdalloc;/*Number of elements that are allocated from heap at the moment because the pool is in completed use. It should be '0' when pool is not in complete use*/ + int max_stdalloc;/*Maximum number of allocations from heap after the pool is completely used that are in active use at any point in the life of the process.*/ + char *name; /*Contains xlator-name:data-type as a string + struct list_head global_list;/*This is used to insert it into the global_list of mempools maintained in 'glusterfs-ctx' +}; +``` + +## Life-cycle +``` +mem_pool_new (data_type, unsigned long count) + +This is a macro which expands to mem_pool_new_fn (sizeof (data_type), count, string-rep-of-data_type) + +struct mem_pool * +mem_pool_new_fn (unsigned long sizeof_type, unsigned long count, char *name) + +Padded-element: + ---------------------------------------- +|list-ptr|mem-pool-address|in-use|Element| + ---------------------------------------- + ``` + +This function allocates the `mem-pool` structure and sets up the pool for use. +`name` parameter above is the `string` containing type of the datatype. This `name` is appended to `xlator-name + ':'` so that it can be easily identified in things like statedump. `count` is the number of elements that need to be allocated. `sizeof_type` is the size of each element. Ideally `('sizeof_type'*'count')` should be the size of the total pool. But to manage the pool using `mem_get`/`mem_put` (will be explained after this section) each element needs to be padded in the front with a `('list', 'mem-pool-address', 'in_use')`. So the actual size of the pool it allocates will be `('padded_sizeof_type'*'count')`. Why these extra elements are needed will be evident after understanding how `mem_get` and `mem_put` are implemented. In this function it just initializes all the `list` structures in front of each element and adds them to the `mem_pool->list` which represent the list of `cold` elements which can be allocated whenever `mem_get` is called on this mem_pool. It remembers mem_pool's start and end addresses in `mem_pool->pool`, `mem_pool->pool_end` respectively. Initializes `mem_pool->cold_count` to `count` and `mem_pool->hot_count` to `0`. This mem-pool will be added to the list of `global_list` maintained in `glusterfs-ctx` + + +``` +void* mem_get (struct mem_pool *mem_pool) + +Initial-list before mem-get +---------------- +| Pool | +| ----------- | ---------------------------------------- ---------------------------------------- +| | pool-list | |<---> |list-ptr|mem-pool-address|in-use|Element|<--->|list-ptr|mem-pool-address|in-use|Element| +| ----------- | ---------------------------------------- ---------------------------------------- +---------------- + +list after mem-get from the pool +---------------- +| Pool | +| ----------- | ---------------------------------------- +| | pool-list | |<--->|list-ptr|mem-pool-address|in-use|Element| +| ----------- | ---------------------------------------- +---------------- + +List when the pool is full: + ---------------- +| Pool | extra element that is allocated +| ----------- | ---------------------------------------- +| | pool-list | | |list-ptr|mem-pool-address|in-use|Element| +| ----------- | ---------------------------------------- + ---------------- +``` + +This function is similar to `malloc()` but it gives memory of type `element` of this pool. When this function is called it increments `mem_pool->alloc_count`, checks if there are any free elements in the pool that can be returned by inspecting `mem_pool->cold_count`. If `mem_pool->cold_count` is non-zero then it means there are elements in the pool which are not in active use. It deletes one element from the list of free elements and decrements `mem_pool->cold_count` and increments `mem_pool->hot_count` to indicate there is one more element in active use. Updates `mem_pool->max_alloc` accordingly. Sets `element->in_use` in the padded memory to `1`. Sets `element->mem_pool` address to this mem_pool also in the padded memory(It is useful for mem_put). Returns the address of the memory after the padded boundary to the caller of this function. In the cases where all the elements in the pool are in active use it `callocs` the element with padded size and sets mem_pool address in the padded memory. To indicate the pool-miss and give useful accounting information of the pool-usage it increments `mem_pool->pool_misses`, `mem_pool->curr_stdalloc`. Updates `mem_pool->max_stdalloc` accordingly. + +``` +void* mem_get0 (struct mem_pool *mem_pool) +``` +Just like `calloc` is to `malloc`, `mem_get0` is to `mem_get`. It memsets the memory to all '0' before returning the element. + + +``` +void mem_put (void *ptr) + +list before mem-put from the pool + ---------------- +| Pool | +| ----------- | ---------------------------------------- +| | pool-list | |<--->|list-ptr|mem-pool-address|in-use|Element| +| ----------- | ---------------------------------------- + ---------------- + +list after mem-put to the pool + ---------------- +| Pool | +| ----------- | ---------------------------------------- ---------------------------------------- +| | pool-list | |<---> |list-ptr|mem-pool-address|in-use|Element|<--->|list-ptr|mem-pool-address|in-use|Element| +| ----------- | ---------------------------------------- ---------------------------------------- + ---------------- + +If mem_put is putting an element not from pool then it is just freed so +no change to the pool + ---------------- +| Pool | +| ----------- | +| | pool-list | | +| ----------- | + ---------------- +``` + +This function is similar to `free()`. Remember that ptr passed to this function is the address of the element, so this function gets the ptr to its head of the padding in front of it. If this memory falls in bettween `mem_pool->pool`, `mem_pool->pool_end` then the memory is part of the 'pool' memory that is allocated so it does some sanity checks to see if the memory is indeed head of the element by checking if `in_use` is set to `1`. It resets `in_use` to `0`. It gets the mem_pool address stored in the padded region and adds this element to the list of free elements. Decreases `mem_pool->hot_count` increases `mem_pool->cold_count`. In the case where padded-element address does not fall in the range of `mem_pool->pool`, `mem_pool->pool_end` it just frees the element and decreases `mem_pool->curr_stdalloc`. + +``` +void +mem_pool_destroy (struct mem_pool *pool) +``` +Deletes this pool from the `global_list` maintained by `glusterfs-ctx` and frees all the memory allocated in `mem_pool_new`. + + +### How to pick pool-size +This varies from work-load to work-load. Create the mem-pool with some random size and run the work-load. Take the statedump after the work-load is complete. In the statedump if `max_alloc` is always less than `cold_count` may be reduce the size of the pool closer to `max_alloc`. On the otherhand if there are lots of `pool-misses` then increase the `pool_size` by `max_stdalloc` to achieve better 'hit-rate' of the pool. diff --git a/doc/developer-guide/dirops-transactions-in-dht.md b/doc/developer-guide/dirops-transactions-in-dht.md new file mode 100644 index 00000000000..909a97001aa --- /dev/null +++ b/doc/developer-guide/dirops-transactions-in-dht.md @@ -0,0 +1,273 @@ +# dirops transactions in dht +Need for transactions during operations on directories arise from two +basic design elements of DHT: + + 1. A directory is created on all subvolumes of dht. Since glusterfs + associates each file-system object with an unique gfid, every + subvolume should have the same unique mapping of (path of directory, + gfid). To elaborate, + * Each subvolume should've same gfid associated with a path to + directory. + * A gfid should not be associated with more than one path in any + subvolume. + + So, entire operations like mkdir, renamedir, rmdir and creation of + directories during self-heal need to be atomic in dht. In other words, + any of these operations shouldn't begin on an inode if one of them is + already in progress on the same inode, till it completes on all + subvolumes of dht. If not, more than one of these operations + happening in parallel can break any or all of the two requirements + listed above. This is referred in the rest of the document by the + name _Atomicity during namespace operations_. + + 2. Each directory has an independent layout persisted on + subvolumes. Each subvolume contains only part of the layout relevant + to it. For performance reasons _and_ since _only_ dht has aggregated + view, this layout is cached in memory of client. To make sure dht + reads or modifies a single complete layout while parallel modifications of the layout are in progress, we need atomicity during layout modification and reading. This is referred in the rest of the document as _Atomicity during layout modification and reading_. + +Rest of the document explains how atomicity is achieved for each of +the case above. + +**Atomicity during layout modification and reading** +File operations a.k.a fops can be classified into two categories based on how they consume layout. + + - Layout writer. Setting of layout during selfheal of a directory is + layout writer of _that_ directory. + - Layout reader. + * Any entry fop like create, unlink, rename, link, symlink, + unlink, mknod, rename, mkdir, rmdir, renamedir which needs layout of the parent directory. Each of these fops are readers of layout on parent directory. + * setting of layout during mkdir of a directory is considered as + a reader of the same directory's layout. The reason for this is that + only a parallel lookup on that directory can be a competing fop that modifies the layout (Other fops need gfid of the directory which can be got only after either lookup or mkdir completes). However, healing of layout is considered as a writer and a single writer blocks all readers. + +*Algorithm* +Atomicity is achieved by locking on the inode of directory whose +layout is being modified or read. The fop used is inodelk. + - Writer acquires blocking inodelk (directory-inode, write-lock) on + all subvolumes serially. The order of subvols in which they are + locked by different clients remains constant for a directory. If locking fails on any subvolume, layout modification is abandoned. + - Reader acquires an inodelk (directory-inode, read-lock) on _any_ + one subvolume. If locking fails on a subvolume (say with + ESTALE/ENOTCONN error), locking can be tried on other subvolumes till + we get one lock. If we cannot get lock on at least one subvolume, + consistency of layout is not guaranteed. Based on the consistency + requirements of fops, they can be failed or continued. + +Reasons why writer has to lock on _all_ subvols: + + - DHT don't have a metadata server and locking is implemented by brick. So, there is no well-defined subvol/brick that can be used as an arbitrator by different clients while acquiring locks. + - readers should acquire as minimum number of locks as possible. In + other words, the algorithm aims to have less synchronization cost to + readers. + - The subvolume to which a directory hashes could be used as a + lock server. However, in the case of an entry fop like create + (/a/b/c) where we want to block modification of layout of b for the + duration of create, we would be required to acquire lock on the + subvol to which /a/b hashes. To find out the hashed-subvol of + /a/b, we would need layout of /a. Note that how there is a dependency + of locking the layouts of ancestors all the way to root. So this + locking is not preferred. Also, note that only the immediate parent + inode is available in arguments of a fop like create. + +**Atomicity during namespace operations** + + - We use locks on inode of parent directory in the namespace of + _"basename"_ during mkdir, rmdir, renamedir and directory + creation phase of self-heal. The exact fop we use is _entrylk + (parent-inode, "basename")_. + - refresh in-memory layout of parent-inode from values stored on backend + - _entrylk (parent-inode, "basename")_ is done on subvolume to which + _"basename" hashes_. So, this operation is a _reader_ of the + layout on _parent-inode_. Which means an _inodelk (parent-inode, + read-lock)_ has to be completed before _entrylk (parent-inode, + "basename")_ is issued. Both the locks have to be held till the + operation is tried on all subvolumes. If acquiring of any/all of + these locks fail, the operation should be failed. + +With the above details, algorithms for mkdir, rmdir, renamedir, +self-heal of directory are explicitly detailed below. + +**Self-heal of a directory** + + - creation of directories on subvolumes is done only during + _named-lookup_ of a directory as we need < parent-inode, + "basename" >. + - If a directory is missing on one or more subvolumes, + * acquire _inodelk (parent-inode, read-lock)_ on _any one_ of the + subvolumes. + * refresh the in-memory layout of parent-inode from values stored on backend + * acquire _entrylk (parent-inode, "basename")_ on the subvolume + to which _"basename"_ hashes. + * If any/all of the locks fail, self-heal is aborted. + * create directories on missing subvolumes. + * release _entrylk (parent-inode, "basename")_. + * release _inodelk (parent-inode, read-lock)_. + + - If layout of a directory needs healing + * acquire _inodelk (directory-inode, write-lock)_ on _all_ the + subvolumes. If locking fails on any of the subvolumes, + self-heal is aborted. Blocking Locks are acquired serially across subvolumes in a _well-defined_ order which is _constant_ across all the healers of a directory. One order could be the order in which subvolumes are stored in the array _children_ of dht xlator. + * heal the layout. + * release _inodelk (directory-inode, write-lock)_ on _all_ the + subvolumes in parallel. + * Note that healing of layout can be done in both _named_ and + _nameless_ lookups of a directory as _only directory-inode_ is needed + for healing and it is available during both. + +**mkdir (parent-inode, "basename")** + +* while creating directory across subvolumes, + + - acquire _inodelk (parent-inode, read-lock)_ on _any one_ of the + subvolumes. + - refresh in-memory layout of parent-inode from values stored on backend + - acquire _entrylk (parent-inode, "basename")_ on the subvolume to + which _"basename"_ hashes. + - If any/all of the above two locks fail, release the locks that + were acquired successfully and mkdir should be failed (as perceived by application). + - do _mkdir (parent-inode, "basename")_ on the subvolume to which + _"basename"_ hashes. If this mkdir fails, mkdir is failed. + - do _mkdir (parent-inode, "basename")_ on the remaining subvolumes. + - release _entrylk (parent-inode, "basename")_. + - release _inodelk (parent-inode, "read-lock")_. +* while setting the layout of a directory, + - acquire _inodelk (directory-inode, read-lock)_ on _any one_ of the + subvolumes. + - If locking fails, cleanup the locks that were acquired + successfully and abort layout setting. Note that we'll have a + directory without a layout till a lookup happens on the + directory. This means entry operations within this directory fail + in this time window. We can also consider failing mkdir. The + problem of dealing with a directory without layout is out of the + scope of this document. + - set the layout on _directory-inode_. + - release _inodelk (directory-inode, read-lock)_. +* Note that during layout setting we consider mkdir as a _reader_ not + _writer_, though it is setting the layout. Reasons are: + - Before any of other readers like create, link etc that operate on + this directory to happen, _gfid_ of this directory has to be + resolved. But _gfid_ is only available only if either of following + conditions are true: + * after mkdir is complete. + * a lookup on the same path happens parallel to in-progress + mkdir. + + But, on completion of any of the above two operations, layout + will be healed. So, none of the _readers_ will happen on a + directory with partial layout. + +* Note that since we've an _entrylk (parent-inode, "basename")_ for + the entire duration of (attempting) creating directories, parallel + mkdirs will no longer contend on _mkdir_ on subvolume _to which "basename" hashes_. But instead, contend on _entrylk (parent-inode, "basename")_ on the subvolume _to which "basename" hashes_. So, we can attempt the _mkdir_ in _parallel_ on all subvolumes instead of two stage mkdir on hashed first and the rest of them in parallel later. However, we need to make sure that mkdir is successful on the subvolume _to which "basename" hashes_ for mkdir to be successful (as perceived by application). In the case of failed mkdir (as perceived by application), a cleanup should be performed on all the subvolumes before _entrylk (parent-inode, "basename")_ is released. + +**rmdir (parent-inode, "basename", directory-inode)** + + - acquire _inodelk (parent-inode, read-lock)_ on _any one_ + subvolume. + - refresh in-memory layout of parent-inode from values stored on backend + - acquire _entrylk (parent-inode, "basename")_ on the subvolume to + which _"basename" hashes_. + - If any/all of the above locks fail, rmdir is failed after cleanup + of the locks that were acquired successfully. + - do _rmdir (parent-inode, "basename")_ on the subvolumes to which + _"basename" doesn't hash to_. + * If successful, continue. + * Else, + * recreate directories on those subvolumes where rmdir + succeeded. + * heal the layout of _directory-inode_. Note that this will have + same synchronization requirements as discussed during layout + healing part of the section "Directoy self-heal" above. + * release _entrylk (parent-inode, "basename")_. + * release _inodelk (parent-inode, read-lock)_. + * fail _rmdir (parent-inode, "basename")_ to application. + - do _rmdir (parent-inode, "basename")_ on the subvolume to which + _"basename" hashes_. + - If successful, continue. + - Else, Go to the failure part of _rmdir (parent-inode, "basename")_ + on subvolumes to which "basename" _doesn't hash to_. + - release _entrylk (parent-inode, "basename")_. + - release _inodelk (parent-inode, read-lock)_. + - return success to application. + +**renamedir (src-parent-inode, "src-basename", src-directory-inode, dst-parent-inode, "dst-basename", dst-directory-inode)** + + - requirement is to prevent any operation in both _src-namespace_ + and _dst-namespace_. So, we need to acquire locks on both + namespaces.We also need to have constant ordering while acquiring + locks during parallel renames of the form _rename (src, dst)_ and + _rename (dst, src)_ to prevent deadlocks. We can sort gfids of + _src-parent-inode_ and _dst-parent-inode_ and use that order to + acquire locks. For the sake of explanation lets say we ended up + with order of _src_ followed by _dst_. + - acquire _inodelk (src-parent-inode, read-lock)_. + - refresh in-memory layout of src-parent-inode from values stored on backend + - acquire _entrylk (src-parent-inode, "src-basename")_. + - acquire _inodelk (dst-parent-inode, read-lock)_. + - refresh in-memory layout of dst-parent-inode from values stored on backend + - acquire _entrylk (dst-parent-inode, "dst-basename")_. + - If acquiring any/all of the locks above fail, + * release the locks that were successfully acquired. + * fail the renamedir operation to application + * done + - do _renamedir ("src", "dst")_ on the subvolume _to which "dst-basename" hashes_. + * If failure, Goto point _If acquiring any/all of the locks above fail_. + * else, continue. + - do _renamedir ("src", "dst")_ on rest of the subvolumes. + * If there is any failure, + * revert the successful renames. + * Goto to point _If acquiring any/all of the locks above fail_. + * else, + - release all the locks acquired. + - return renamedir as success to application. + +**Some examples of races** +This section gives concrete examples of races that can result in inconsistencies explained in the beginning of the document. + +Some assumptions are: + +* We consider an example distribute of three subvols s1, s2 and s3. +* For examples of renamedir ("src", "dst"), _src_ hashes to s1 and _dst_ hashes to s2. _src_ and _dst_ are associated with _gfid-src_ and _gfid-dst_ respectively +* For non renamedir examples, _dir_ is the name of directory and it hashes to s1. + +And the examples are: + + - mkdir vs rmdir - inconsistency in namespace. + * mkdir ("dir", gfid1) is complete on s1 + * rmdir is issued on same directory. Note that, since rmdir needs a gfid, a lookup should be complete before rmdir. lookup creates the directory on rest of the subvols as part of self-heal. + * rmdir (gfid1) deletes directory from all subvols. + * A new mkdir ("dir", gfid2) is issued. It is successful on s1 associating "dir" with gfid2. + * mkdir ("dir", gfid1) resumes and creates directory on s2 and s3 associating "dir" with gfid1. + * mkdir ("dir", gfid2) fails with EEXIST on s2 and s3. Since, EEXIST errors are ignored, mkdir is considered successful to application. + * In this example we have multiple inconsitencies + * "dir" is associated with gfid1 on s2, s3 and with gfid2 on s1 + * Even if mkdir ("dir", gfid2) was not issued, we would've a case of a directory magically reappearing after a successful rmdir. + - lookup heal vs rmdir + * rmdir ("dir", gfid1) is issued. It is successful on s2 and s3 (non-hashed subvols for name "dir") + * lookup ("dir") is issued. Since directory is present on s1 yet, it is created on s2 and s3 associating with gfid1 as part of self-heal + * rmdir ("dir", gfid1) is complete on s1 and it is successful + * Another lookup ("dir") creates the directory on s1 too + * "dir" magically reappears after a successful rmdir + - lookup heal (src) vs renamedir ("src", "dst") + * renamedir ("src", "dst") complete on s2 + * lookup ("src") recreates _src_ with _gfid-src_ on s2 + * renamedir ("src", "dst") completes on s1, s3. After rename is complete path _dst_ will be associated with gfid _gfid-src_ + * Another lookup ("src") recreates _src_ on subvols s1 and s3, associating it with gfid _gfid-src_ + * Inconsistencies are + * after a successful renamedir ("src", "dst"), both src and dst exist + * Two directories - src and dst - are associated with same gfid. One common symptom is that some entries (of the earlier _src_ and current _dst_ directory) being missed out in readdir listing as the gfid handle might be pointing to the empty healed directory than the actual directory containing entries + - lookup heal (dst) vs renamedir ("src", "dst") + * dst exists and empty when renamdir started + * dst doesn't exist when renamedir started + - renamedir ("src", "dst") complete on s2 and s3 + - lookup ("dst") creates _dst_ associating it with _gfid-src_ on s1 + - An entry is created in _dst_ on either s1 + - renamedir ("src", "dst") on s1 will result in a directory _dst/dst_ as _dst_ is no longer empty and _man 2 rename_ states that if _dst_ is not empty, _src_ is renamed _as a subdirectory of dst_ + - A lookup ( _dst/dst_) creates _dst/dst_ on s2 and s3 associating with _gfid-src_ as part of self-heal + - Inconsistencies are: + * Two directories - _dst_ and _dst/dst_ - exist even though both of them didn't exist at the beginning of renamedir + * Both _dst_ and _dst/dst_ have same gfid - _gfid-src_. As observed earlier, symptom might be directory listing being incomplete + - mkdir (dst) vs renamedir ("src", "dst") + - rmdir (src) vs renamedir ("src", "dst") + - rmdir (dst) vs renamedir ("src", "dst") diff --git a/doc/developer-guide/ec-implementation.md b/doc/developer-guide/ec-implementation.md new file mode 100644 index 00000000000..77e62583caa --- /dev/null +++ b/doc/developer-guide/ec-implementation.md @@ -0,0 +1,588 @@ +Erasure coding implementation +============================= + +This document provides information about how [erasure code][1] has +been implemented into ec translator. It describes the algorithm used +and the optimizations made, but it doesn't contain a full description +of the mathematical background needed to understand erasure coding in +general. It either describes the other parts of ec not directly +related to the encoding/decoding procedure, like synchronization or +fop management. + + +Introduction +------------ + +EC is based on [Reed-Solomon][2] erasure code. It's a very old code. +It's not considered the best one nowadays, but is good enough and it's +one of the few codes that is not covered by any patent and can be +freely used. + +To define the Reed-Solomon code we use 3 parameters: + + * __Key fragments (K)__ + It represents the minimum number of healthy fragments that will be + needed to be able to recover the original data. Any subset of K + out of the total number of fragments will serve. + + * __Redundancy fragments (R)__ + It represents the number of extra fragments to compute for each + original data block. This value determines how many fragments can + be lost before being unable to recover the original data. + + * __Fragment size (S)__ + This determines the size of each fragment. The original data + block size is computed as S * K. Currently this values is fixed + to 512 bytes. + + * __Total number of fragments (N = K + R)__ + This isn't a real parameter but it will be useful to simplify + the following descriptions. + +From the point of view of the implementation, it only consists on +matrix multiplications. There are two kinds of matrices to use for +Reed-Solomon: + + * __[Systematic][3]__ + This kind of matrix has the particularity that K of the encoded + fragments are simply a copy of the original data, divided into K + pieces. Thus no real encoding needs to be done for them and only + the R redundancy fragments need to be computed. + + This kind of matrices contain one KxK submatrix that is the + [identity matrix][4]. + + * __Non-systematic__ + This kind of matrix doesn't contain an identity submatrix. This + means that all of the N fragments need to be encoded, requiring + more computation. On the other hand, these matrices have some nice + properties that allow faster implementations of some algorithms, + like the matrix inversion used to decode the data. + + Another advantage of non-systematic matrices is that the decoding + time is constant, independently of how many fragments are lost, + while systematic approach can suffer from performance degradation + when one fragment is lost. + +All non-systematic matrices can be converted to systematic ones, but +then we lose the good properties of the non-systematic. We have to +choose betwee best peek performance (systematic) and performance +stability (non-systematic). + + +Encoding procedure +------------------ + +To encode a block of data we need a KxN matrix where each subset of K +rows is [linearly independent][5]. In other words, the determinant of +each KxK submatrix is not 0. + +There are some known ways to obtain this kind of matrices. EC uses a +small variation of a matrix known as [Vandermonde Matrix][6] where +each element of the matrix is defined as: + + a(i, j) = i ^ (K - j) + + where i is the row from 1 to N, and j is the column from 1 to K. + +This is exactly the Vandermonde Matrix but with the elements of each +row in reverse order. This change is made to be able to implement a +small optimization in the matrix multiplication. + +Once we have the matrix, we only need to compute the multiplication +of this matrix by a vector composed of K elements of data coming from +the original data block. + + / \ / \ + | 1 1 1 1 1 | / \ | a + b + c + d + e = t | + | 16 8 4 2 1 | | a | | 16a + 8b + 4c + 2d + e = u | + | 81 27 9 3 1 | | b | = | 81a + 27b + 9c + 3d + e = v | + | 256 64 16 4 1 | * | c | | 256a + 64b + 16c + 4d + e = w | + | 625 125 25 5 1 | | d | | 625a + 125b + 25c + 5d + e = x | + | 1296 216 36 6 1 | | e | | 1296a + 216b + 36c + 6d + e = y | + | 2401 343 49 7 1 | \ / | 2401a + 343b + 49c + 7d + e = z | + \ / \ / + +The optimization that can be done here is this: + + 16a + 8b + 4c + 2d + e = 2(2(2(2a + b) + c) + d) + e + +So all the multiplications are always by the number of the row (2 in +this case) and we don't need temporal storage for intermediate +results: + + a *= 2 + a += b + a *= 2 + a += c + a *= 2 + a += d + a *= 2 + a += e + +Once we have the result vector, each element is a fragment that needs +to be stored in a separate place. + + +Decoding procedure +------------------ + +To recover the data we need exactly K of the fragments. We need to +know which K fragments we have (i.e. the original row number from +which each fragment was calculated). Once we have this data we build +a square KxK matrix composed by the rows corresponding to the given +fragments and invert it. + +With the inverted matrix, we can recover the original data by +multiplying it with the vector composed by the K fragments. + +In our previous example, if we consider that we have recovered +fragments t, u, v, x and z, corresponding to rows 1, 2, 3, 5 and 7, +we can build the following matrix: + + / \ + | 1 1 1 1 1 | + | 16 8 4 2 1 | + | 81 27 9 3 1 | + | 625 125 25 5 1 | + | 2401 343 49 7 1 | + \ / + +And invert it: + + / \ + | 1/48 -1/15 1/16 -1/48 1/240 | + | -17/48 16/15 -15/16 13/48 -11/240 | + | 101/48 -86/15 73/16 -53/48 41/240 | + | -247/48 176/15 -129/16 83/48 -61/240 | + | 35/8 -7 35/8 -7/8 1/8 | + \ / + +Multiplying it by the vector (t, u, v, x, z) we recover the original +data (a, b, c, d, e): + + / \ / \ / \ + | 1/48 -1/15 1/16 -1/48 1/240 | | t | | a | + | -17/48 16/15 -15/16 13/48 -11/240 | | u | | b | + | 101/48 -86/15 73/16 -53/48 41/240 | * | v | = | c | + | -247/48 176/15 -129/16 83/48 -61/240 | | x | | d | + | 35/8 -7 35/8 -7/8 1/8 | | z | | e | + \ / \ / \ / + + +Galois Field +------------ + +This encoding/decoding procedure is quite complex to compute using +regular mathematical operations and it's not well suited for what +we want to do (note that matrix elements can grow unboundly). + +To solve this problem, exactly the same procedure is done inside a +[Galois Field][7] of characteristic 2, which is a finite field with +some interesting properties that make it specially useful for fast +operations using computers. + +There are two main differences when we use this specific Galois Field: + + * __All regular additions are replaced by bitwise xor's__ + For todays computers it's not really faster to execute an xor + compared to an addition, however replacing additions by xor's + inside a multiplication has many advantages (we will make use of + this to optimize the multiplication). + + Another consequence of this change is that additions and + substractions are really the same xor operation. + + * __The elements of the matrix are bounded__ + The field uses a modulus that keep all possible elements inside + a delimited region, avoiding really big numbers and fixing the + number of bits needed to represent each value. + + In the current implementation EC uses 8 bits per field element. + +It's very important to understand how multiplications are computed +inside a Galois Field to be able to understand how has it been +optimized. + +We'll start with a simple 'old school' multiplication but in base 2. +For example, if we want to multiply 7 * 5 (111b * 101b in binary), we +do the following: + + 1 1 1 (= 7) + * 1 0 1 (= 5) + ----------- + 1 1 1 (= 7) + + 0 0 0 (= 0) + + 1 1 1 (= 7) + ----------- + 1 0 0 0 1 1 (= 35) + +This is quite simple. Note that the addition of the third column +generates a carry that is propagated to all the other left columns. + +The next step is to define the modulus of the field. Suppose we use +11 as the modulus. Then we convert the result into an element of the +field by dividing by the modulus and taking the residue. We also use +the 'old school' method in binary: + + + 1 0 0 0 1 1 (= 35) | 1 0 1 1 (= 11) + - 0 0 0 0 ---------------- + --------- 0 1 1 (= 3) + 1 0 0 0 1 + - 1 0 1 1 + ----------- + 0 0 1 1 0 1 + - 1 0 1 1 + ------------- + 0 0 1 0 (= 2) + +So, 7 * 5 in a field with modulus 11 is 2. Note that the main +objective in each iteration of the division is to make higher bits +equal to 0 when possible (if it's not possible in one iteration, it +will be zeroed on the next). + +If we do the same but changing additions with xors we get this: + + 1 1 1 (= 7) + * 1 0 1 (= 5) + ----------- + 1 1 1 (= 7) + x 0 0 0 (= 0) + x 1 1 1 (= 7) + ----------- + 1 1 0 1 1 (= 27) + +In this case, the xor of the third column doesn't generate any carry. + +Now we need to divide by the modulus. We can also use 11 as the +modulus since it still satisfies the needed conditions to work on a +Galois Field of characteristic 2 with 3 bits: + + 1 1 0 1 1 (= 27) | 1 0 1 1 (= 11) + x 1 0 1 1 ---------------- + --------- 1 1 1 (= 7) + 0 1 1 0 1 + x 1 0 1 1 + ----------- + 0 1 1 0 1 + x 1 0 1 1 + ------------- + 0 1 1 0 (= 6) + +Note that, in this case, to make zero the higher bit we need to +consider the result of the xor operation, not the addition operation. + +So, 7 * 5 in a Galois Field of 3 bits with modulus 11 is 6. + + +Optimization +------------ + +To compute all these operations in a fast way some methods have been +traditionally used. Maybe the most common is the [lookup table][8]. + +The problem with this method is that it requires 3 lookups for each +byte multiplication, greatly amplifying the needed memory bandwidth +and making it difficult to take advantage of any SIMD support on the +processor. + +What EC does to improve the performance is based on the following +property (using the 3 bits Galois Field of the last example): + + A * B mod N = (A * b{2} * 4 mod N) x + (A * b{1} * 2 mod N) x + (A * b{0} mod N) + +This is basically a rewrite of the steps made in the previous example +to multiply two numbers but moving the modulus calculation inside each +intermediate result. What we can see here is that each term of the +xor can be zeroed if the corresponding bit of B is 0, so we can ignore +that factor. If the bit is 1, we need to compute A multiplied by a +power of two and take the residue of the division by the modulus. We +can precompute these values: + + A0 = A (we don't need to compute the modulus here) + A1 = A0 * 2 mod N + A2 = A1 * 2 mod N + +Having these values we only need to add those corresponding to bits +set to 1 in B. Using our previous example: + + A = 1 1 1 (= 7) + B = 1 0 1 (= 5) + + A0 = 1 1 1 (= 7) + A1 = 1 1 1 * 1 0 mod 1 0 1 1 = 1 0 1 (= 5) + A2 = 1 0 1 * 1 0 mod 1 0 1 1 = 0 0 1 (= 1) + + Since only bits 0 and 2 are 1 in B, we add A0 and A2: + + A0 + A2 = 1 1 1 x 0 0 1 = 1 1 0 (= 6) + +If we carefully look at what we are doing when computing each Ax, we +see that we do two basic things: + + - Shift the original value one bit to the left + - If the highest bit is 1, xor with the modulus + +Let's write this in a detailed way (representing each bit): + + Original value: a{2} a{1} a{0} + Shift 1 bit: a{2} a{1} a{0} 0 + + If a{2} is 0 we already have the result: + a{1} a{0} 0 + + If a{2} is 1 we need to xor with the modulus: + 1 a{1} a{0} 0 x 1 0 1 1 = a{1} (a{0} x 1) 1 + +An important thing to see here is that if a{2} is 0, we can get the +same result by xoring with all 0 instead of the modulus. For this +reason we can rewrite the modulus as this: + + Modulus: a{2} 0 a{2} a{2} + +This means that the modulus will be 0 0 0 0 is a{2} is 0, so the value +won't change, and it will be 1 0 1 1 if a{2} is 1, giving the correct +result. So, the computation is simply: + + Original value: a{2} a{1} a{0} + Shift 1 bit: a{2} a{1} a{0} 0 + Apply modulus: a{1} (a{0} x a{2}) a{2} + +We can compute all Ax using this method. We'll get this: + + A0 = a{2} a{1} a{0} + A1 = a{1} (a{0} x a{2}) a{2} + A2 = (a{0} x a{2}) (a{1} x a{2}) a{1} + +Once we have all terms, we xor the ones corresponding to the bits set +to 1 in B. In out example this will be A0 and A2: + + Result: (a{2} x a{0} x a{2}) (a{1} x a{1} x a{2}) (a{0} x a{1}) + +We can easily see that we can remove some redundant factors: + + Result: a{0} a{2} (a{0} x a{1}) + +This way we have come up with a simply set of equations to compute the +multiplication of any number by 5. If A is 1 1 1 (= 7), the result +must be 1 1 0 (= 6) using the equations, as we expected. If we try +another numbe for A, like 0 1 0 (= 2), the result must be 0 0 1 (= 1). + +This seems a really fast way to compute the multiplication without +using any table lookup. The problem is that this is only valid for +B = 5. For other values of B another set of equations will be found. +To solve this problem we can pregenerate the equations for all +possible values of B. Since the Galois Field we use is small, this is +feasible. + +One thing to be aware of is that, in general, two equations for +different bits of the same B can share common subexpressions. This +gives space for further optimizations to reduce the total number of +xors used in the final equations for a given B. However this is not +easy to find, since finding the smallest number of xors that give the +correct result is an NP-Problem. For EC an exhaustive search has been +made to find the best combinations for each possible value. + + +Implementation +-------------- + +All this seems great from the hardware point of view, but implementing +this using normal processor instructions is not so easy because we +would need a lot of shifts, ands, xors and ors to move the bits of +each number to the correct position to compute the equation and then +another shift to put each bit back to its final place. + +For example, to implement the functions to multiply by 5, we would +need something like this: + + Bit 2: T2 = (A & 1) << 2 + Bit 1: T1 = (A & 4) >> 1 + Bit 0: T0 = ((A >> 1) x A) & 1 + Result: T2 + T1 + T0 + +This doesn't look good. So here we make a change in the way we get +and process the data: instead of reading full numbers into variables +and operate with them afterwards, we use a single independent variable +for each bit of the number. + +Assume that we can read and write independent bits from memory (later +we'll see how to solve this problem when this is not possible). In +this case, the code would look something like this: + + Bit 2: T2 = Mem[2] + Bit 1: T1 = Mem[1] + Bit 0: T0 = Mem[0] + Computation: T1 ^= T0 + Store result: Mem[2] = T0 + Mem[1] = T2 + Mem[0] = T1 + +Note that in this case we handle the final reordering of bits simply +by storing the right variable to the right place, without any shifts, +ands nor ors. In fact we only have memory loads, memory stores and +xors. Note also that we can do all the computations directly using the +variables themselves, without additional storage. This true for most +of the values, but in some cases an additional one or two temporal +variables will be needed to store intermediate results. + +The drawback of this approach is that additions, that are simply a +xor of two numbers will need as many xors as bits are in each number. + + +SIMD optimization +----------------- + +So we have a good way to compute the multiplications, but even using +this we'll need several operations for each byte of the original data. +We can improve this by doing multiple multiplications using the same +set of instructions. + +With the approach taken in the implementation section, we can see that +in fact it's really easy to add SIMD support to this method. We only +need to store in each variable one bit from multiple numbers. For +example, when we load T2 from memory, instead of reading the bit 2 of +the first number, we can read the bit 2 of the first, second, third, +fourth, ... numbers. The same can be done when loading T1 and T0. + +Obviously this needs to have a special encoding of the numbers into +memory to be able to do that in a single operation, but since we can +choose whatever encoding we want for EC, we have chosen to have +exactly that. We interpret the original data as a stream of bits, and +we split it into subsequences of length L, each containing one bit of +a number. Every S subsequences form a set of numbers of S bits that +are encoded and decoded as a single group. This repeats for any +remaining data. + +For example, in a simple case with L = 8 and S = 3, the original data +would contain something like this (interpreted as a sequence of bits, +offsets are also bit-based): + + Offset 0: a{0} b{0} c{0} d{0} e{0} f{0} g{0} h{0} + Offset 8: a{1} b{1} c{1} d{1} e{1} f{1} g{1} h{1} + Offset 16: a{2} b{2} c{2} d{2} e{2} f{2} g{2} h{2} + Offset 24: i{0} j{0} k{0} l{0} m{0} n{0} o{0} p{0} + Offset 32: i{1} j{1} k{1} l{1} m{1} n{1} o{1} p{1} + Offset 40: i{2} j{2} k{2} l{2} m{2} n{2} o{2} p{2} + +Note: If the input file is not a multiple of S * L, 0-padding is done. + +Here we have 16 numbers encoded, from A to P. This way we can easily +see that reading the first byte of the file will read all bits 0 of +number A, B, C, D, E, F, G and H. The same happens with bits 1 and 2 +when we read the second and third bytes respectively. Using this +encoding and the implementation described above, we can see that the +same set of instructions will be computing the multiplication of 8 +numbers at the same time. + +This can be further improved if we use L = 64 with 64 bits variables +on 64-bits processor. It's even faster if we use L = 128 using SSE +registers or L = 256 using AVX registers on Intel processors. + +Currently EC uses L = 512 and S = 8. This means that numbers are +packed in blocks of 512 bytes and gives space for even bigger +processor registers up to 512 bits. + + +Conclusions +----------- + +This method requires a single variable/processor register for each +bit. This can be challenging if we want to avoid additional memory +accesses, even if we use modern processors that have many registers. +However, the implementation we chose for the Vandermonde Matrix +doesn't require temporary storage, so we don't need a full set of 8 +new registers (one for each bit) to store partial computations. +Additionally, the computation of the multiplications requires, at +most, 2 extra registers, but this is afordable. + +Xors are a really fast operation in modern processors. Intel CPU's +can dispatch up to 3 xors per CPU cycle if there are no dependencies +with ongoing previous instructions. Worst case is 1 xor per cycle. So, +in some configurations, this method could be very near to the memory +speed. + +Another interesting thing of this method is that all data it needs to +operate is packed in small sequential blocks of memory, meaning that +it can take advantage of the faster internal CPU caches. + + +Results +------- + +For the particular case of 8 bits, EC can compute each multiplication +using 12.8 xors on average (without counting 0 and 1 that do not +require any xor). Some numbers require less, like 2 that only requires +3 xors. + +Having all this, we can check some numbers to see the performance of +this method. + +Maybe the most interesting thing is the average number of xors needed +to encode a single byte of data. To compute this we'll need to define +some variables: + + * K: Number of data fragments + * R: Number of redundancy fragments + * N: K + R + * B: Number of bits per number + * A: Average number of xors per number + * Z: Bits per CPU register (can be up to 256 for AVX registers) + * X: Average number of xors per CPU cycle + * L: Average cycles per load + * S: Average cycles per store + * G: Core speed in Hz + +_Total number of bytes processed for a single matrix multiplication_: + + * __Read__: K * B * Z / 8 + * __Written__: N * B * Z / 8 + +_Total number of memory accesses_: + + * __Loads__: K * B * N + * __Stores__: B * N + +> We need to read the same K * B * Z bits, in registers of Z bits, N +> times, one for each row of the matrix. However the last N - 1 reads +> could be made from the internal CPU caches if conditions are good. + +_Total number of operations_: + + * __Additions__: (K - 1) * N + * __Multiplications__: K * N + +__Total number of xors__: B * (K - 1) * N + A * K * N = + N * ((A + B) * K - B) + +__Xors per byte__: 8 * N * ((A + B) * K - B) / (K * B * Z) + +__CPU cycles per byte__: 8 * N * ((A + B) * K - B) / (K * B * Z * X) + + 8 * L * N / Z + (loads) + 8 * S * N / (K * Z) (stores) + +__Bytes per second__: G / {CPU cycles per byte} + +Some xors per byte numbers for specific configurations (B=8): + + Z=64 Z=128 Z=256 + K=2/R=1 0.79 0.39 0.20 + K=4/R=2 1.76 0.88 0.44 + K=4/R=3 2.06 1.03 0.51 + K=8/R=3 3.40 1.70 0.85 + K=8/R=4 3.71 1.86 0.93 + K=16/R=4 6.34 3.17 1.59 + + + +[1]: https://en.wikipedia.org/wiki/Erasure_code +[2]: https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction +[3]: https://en.wikipedia.org/wiki/Systematic_code +[4]: https://en.wikipedia.org/wiki/Identity_matrix +[5]: https://en.wikipedia.org/wiki/Linear_independence +[6]: https://en.wikipedia.org/wiki/Vandermonde_matrix +[7]: https://en.wikipedia.org/wiki/Finite_field +[8]: https://en.wikipedia.org/wiki/Finite_field_arithmetic#Implementation_tricks diff --git a/doc/developer-guide/fuse-interrupt.md b/doc/developer-guide/fuse-interrupt.md new file mode 100644 index 00000000000..ec991b81ec5 --- /dev/null +++ b/doc/developer-guide/fuse-interrupt.md @@ -0,0 +1,211 @@ +# Fuse interrupt handling + +## Conventions followed + +- *FUSE* refers to the "wire protocol" between kernel and userspace and + related specifications. +- *fuse* refers to the kernel subsystem and also to the GlusterFs translator. + +## FUSE interrupt handling spec + +The [Linux kernel FUSE documentation](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/fuse.txt?h=v4.18#n148) +desrcibes how interrupt handling happens in fuse. + +## Interrupt handling in the fuse translator + +### Declarations + +This document describes the internal API in the fuse translator with which +interrupt can be handled. + +The API being internal (to be used only in fuse-bridge.c; the functions are +not exported to a header file). + +``` +enum fuse_interrupt_state { + /* ... */ + INTERRUPT_SQUELCHED, + INTERRUPT_HANDLED, + /* ... */ +}; +typedef enum fuse_interrupt_state fuse_interrupt_state_t; +struct fuse_interrupt_record; +typedef struct fuse_interrupt_record fuse_interrupt_record_t; +typedef void (*fuse_interrupt_handler_t)(xlator_t *this, + fuse_interrupt_record_t *); +struct fuse_interrupt_record { + fuse_in_header_t fuse_in_header; + void *data; + /* + ... + */ +}; + +fuse_interrupt_record_t * +fuse_interrupt_record_new(fuse_in_header_t *finh, + fuse_interrupt_handler_t handler); + +void +fuse_interrupt_record_insert(xlator_t *this, fuse_interrupt_record_t *fir); + +gf_boolean_t +fuse_interrupt_finish_fop(call_frame_t *frame, xlator_t *this, + gf_boolean_t sync, void **datap); + +void +fuse_interrupt_finish_interrupt(xlator_t *this, fuse_interrupt_record_t *fir, + fuse_interrupt_state_t intstat, + gf_boolean_t sync, void **datap); +``` + +The code demonstrates the usage of the API through `fuse_flush()`. (It's a +dummy implementation only for demonstration purposes.) Flush is chosen +because a `FLUSH` interrupt is easy to trigger (see +*tests/features/interrupt.t*). Interrupt handling for flush is switched on +by `--fuse-flush-handle-interrupt` (a hidden glusterfs command line flag). +The implementation of flush interrupt is contained in the +`fuse_flush_interrupt_handler()` function and blocks guarded by the + +``` +if (priv->flush_handle_interrupt) { ... +``` + +conditional (where `priv` is a `*fuse_private_t`). + +### Overview + +"Regular" fuse fops and interrupt handlers interact via a list containing +interrupt records. + +If a fop wishes to have its interrupts handled, it needs to set up an +interrupt record and insert it into the list; also when it's to finish +(ie. in its "cbk" stage) it needs to delete the record from the list. + +If no interrupt happens, basically that's all to it - a list insertion +and deletion. + +However, if an interrupt comes for the fop, the interrupt FUSE request +will carry the data identifying an ongoing fop (that is, its `unique`), +and based on that, the interrupt record will be looked up in the list, and +the specific interrupt handler (a member of the interrupt record) will be +called. + +Usually the fop needs to share some data with the interrupt handler to +enable it to perform its task (also shared via the interrupt record). +The interrupt API offers two approaches to manage shared data: +- _Async or reference-counting strategy_: from the point on when the interrupt + record is inserted to the list, it's owned jointly by the regular fop and + the prospective interrupt handler. Both of them need to check before they + return if the other is still holding a reference; if not, then they are + responsible for reclaiming the shared data. +- _Sync or borrow strategy_: the interrupt handler is considered a borrower + of the shared data. The interrupt handler should not reclaim the shared + data. The fop will wait for the interrupt handler to finish (ie., the borrow + to be returned), then it has to reclaim the shared data. + +The user of the interrupt API need to call the following functions to +instrument this control flow: +- `fuse_interrupt_record_insert()` in the fop to insert the interrupt record to + the list; +- `fuse_interrupt_finish_fop()`in the fop (cbk) and +- `fuse_interrupt_finish_interrupt()`in the interrupt handler + +to perform needed synchronization at the end their tenure. The data management +strategies are implemented by the `fuse_interrupt_finish_*()` functions (which +have an argument to specify which strategy to use); these routines take care +of freeing the interrupt record itself, while the reclamation of the shared data +is left to the API user. + +### Usage + +A given FUSE fop can be enabled to handle interrupts via the following +steps: + +- Define a handler function (of type `fuse_interrupt_handler_t`). + It should implement the interrupt handling logic and in the end + call (directly or as async callback) `fuse_interrupt_finish_interrupt()`. + The `intstat` argument to `fuse_interrupt_finish_interrupt` should be + either `INTERRUPT_SQUELCHED` or `INTERRUPT_HANDLED`. + - `INTERRUPT_SQUELCHED` means that the interrupt could not be delivered + and the fop is going on uninterrupted. + - `INTERRUPT_HANDLED` means that the interrupt was actually handled. In + this case the fop will be answered from interrupt context with errno + `EINTR` (that is, the fop should not send a response to the kernel). + + (the enum `fuse_interrupt_state` includes further members, which are reserved + for internal use). + + We return to the `sync` and `datap` arguments later. +- In the `fuse_<FOP>` function create an interrupt record using + `fuse_interrupt_record_new()`, passing the incoming `fuse_in_header` and + the above handler function to it. + - Arbitrary further data can be referred to via the `data` member of the + interrupt record that is to be passed on from fop context to + interrupt context. +- When it's set up, pass the interrupt record to + `fuse_interrupt_record_insert()`. +- In `fuse_<FOP>_cbk` call `fuse_interrupt_finish_fop()`. + - `fuse_interrupt_finish_fop()` returns a Boolean according to whether the + interrupt was handled. If it was, then the FUSE request is already + answered and the stack gets destroyed in `fuse_interrupt_finish_fop` so + `fuse_<FOP>_cbk()` can just return (zero). Otherwise follow the standard + cbk logic (answer the FUSE request and destroy the stack -- these are + typically accomplished by `fuse_err_cbk()`). +- The last two argument of `fuse_interrupt_finish_fop()` and + `fuse_interrupt_finish_interrupt()` are `gf_boolean_t sync` and + `void **datap`. + - `sync` represents the strategy for freeing the interrupt record. The + interrupt handler and the fop handler are in race to get at the interrupt + record first (interrupt handler for purposes of doing the interrupt + handling, fop handler for purposes of deactivating the interrupt record + upon completion of the fop handling). + - If `sync` is true, then the fop handler will wait for the interrupt + handler to finish and it takes care of freeing. + - If `sync` is false, the loser of the above race will perform freeing. + + Freeing is done within the respective interrupt finish routines, except + for the `data` field of the interrupt record; with respect to that, see + the discussion of the `datap` parameter below. The strategy has to be + consensual, that is, `fuse_interrupt_finish_fop()` and + `fuse_interrupt_finish_interrupt()` must pass the same value for `sync`. + If dismantling the resources associated with the interrupt record is + simple, `sync = _gf_false` is the suggested choice; `sync = _gf_true` can + be useful in the opposite case, when dismantling those resources would + be inconvenient to implement in two places or to enact in non-fop context. + - If `datap` is `NULL`, the `data` member of the interrupt record will be + freed within the interrupt finish routine. If it points to a valid + `void *` pointer, and if caller is doing the cleanup (see `sync` above), + then that pointer will be directed to the `data` member of the interrupt + record and it's up to the caller what it's doing with it. + - If `sync` is true, interrupt handler can use `datap = NULL`, and + fop handler will have `datap` point to a valid pointer. + - If `sync` is false, and handlers pass a pointer to a pointer for + `datap`, they should check if the pointed pointer is NULL before + attempting to deal with the data. + +### FUSE answer for the interrupted fop + +The kernel acknowledges a successful interruption for a given FUSE request +if the filesystem daemon answers it with errno EINTR; upon that, the syscall +which induced the request will be abruptly terminated with an interrupt, rather +than returning a value. + +In glusterfs, this can be arranged in two ways. + +- If the interrupt handler wins the race for the interrupt record, ie. + `fuse_interrupt_finish_fop()` returns true to `fuse_<FOP>_cbk()`, then, as + said above, `fuse_<FOP>_cbk()` does not need to answer the FUSE request. + That's because then the interrupt handler will take care about answering + it (with errno EINTR). +- If `fuse_interrupt_finish_fop()` returns false to `fuse_<FOP>_cbk()`, then + this return value does not inform the fop handler whether there was an interrupt + or not. This return value occurs both when fop handler won the race for the + interrupt record against the interrupt handler, and when there was no interrupt + at all. + + However, the internal logic of the fop handler might detect from other + circumstances that an interrupt was delivered. For example, the fop handler + might be sleeping, waiting for some data to arrive, so that a premature + wakeup (with no data present) occurs if the interrupt handler intervenes. In + such cases it's the responsibility of the fop handler to reply the FUSE + request with errro EINTR. diff --git a/doc/developer-guide/gfapi-symbol-versions.md b/doc/developer-guide/gfapi-symbol-versions.md new file mode 100644 index 00000000000..e4f4fe9f052 --- /dev/null +++ b/doc/developer-guide/gfapi-symbol-versions.md @@ -0,0 +1,270 @@ + +## Symbol Versions and SO_NAMEs + + In general, adding new APIs to a shared library does not require that +symbol versions be used or the the SO_NAME be "bumped." These actions +are usually reserved for when a major change is introduced, e.g. many +APIs change or a signficant change in the functionality occurs. + + Over the normal lifetime of a When a new API is added, the library is +recompiled, consumers of the new API are able to do so, and existing, +legacy consumers of the original API continue as before. If by some +chance an old copy of the library is installed on a system, it's unlikely +that most applications will be affected. New applications that use the +new API will incur a run-time error terminate. + + Bumping the SO_NAME, i.e. changing the shared lib's file name, e.g. +from libfoo.so.0 to libfoo.so.1, which also changes the ELF SO_NAME +attribute inside the file, works a little differently. libfoo.so.0 +contains only the old APIs. libfoo.so.1 contains both the old and new +APIs. Legacy software that was linked with libfoo.so.0 continues to work +as libfoo.so.0 is usually left installed on the system. New software that +uses the new APIs is linked with libfoo.so.1, and works as long as +long as libfoo.so.1 is installed on the system. Accidentally (re)installing +libfoo.so.0 doesn't break new software as long as reinstalling doesn't +erase libfoo.so.1. + + Using symbol versions is somewhere in the middle. The shared library +file remains libfoo.so.0 forever. Legacy APIs may or may not have an +associated symbol version. New APIs may or may not have an associated +symbol version either. In general symbol versions are reserved for APIs +that have changed. Either the function's signature has changed, i.e. the +return time or the number of paramaters, and/or the parameter types have +changed. Another reason for using symbol versions on an API is when the +behaviour or functionality of the API changes dramatically. As with a +library that doesn't use versioned symbols, old and new applications +either find or don't find the versioned symbols they need. If the versioned +symbol doesn't exist in the installed library, the application incurs a +run-time error and terminates. + + GlusterFS wanted to keep tight control over the APIs in libgfapi. +Originally bumping the SO_NAME was considered, and GlusterFS-3.6.0 was +released with libgfapi.so.7. Not only was "7" a mistake (it should have +been "6"), but it was quickly pointed out that many dependent packages +that use libgfapi would be forced to be recompiled/relinked. Thus no +packages of 3.6.0 were ever released and 3.6.1 was quickly released with +libgfapi.so.0, but with symbol versions. There's no strong technical +reason for either; the APIs have not changed, only new APIs have been +added. It's merely being done in anticipation that some APIs might change +sometime in the future. + + Enough about that now, let's get into the nitty gritty—— + +## Adding new APIs + +### Adding a public API. + + This is the default, and the easiest thing to do. Public APIs have +declarations in either glfs.h, glfs-handles.h, or, at your discretion, +in a new header file intended for consumption by other developers. + +Here's what you need to do to add a new public API: + ++ Write the declaration, e.g. in glfs.h: + +```C + int glfs_dtrt (const char *volname, void *stuff) __THROW +``` + ++ Write the definition, e.g. in glfs-dtrt.c: + +```C + int + pub_glfs_dtrt (const char *volname, void *stuff) + { + ... + return 0; + } +``` + ++ Add the symbol version magic for ELF, gnu toolchain to the definition. + + following the definition of your new function in glfs-dtrtops.c, add a + line like this: + +```C + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dtrt, 3.7.0) +``` + + The whole thing should look like: + +```C + int + pub_glfs_dtrt (const char *volname, void *stuff) + { + ... + } + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dtrt, 3.7.0); +``` + + In this example, 3.7.0 refers to the Version the symbol will first + appear in. There's nothing magic about it, it's just a string token. + The current versions we have are 3.4.0, 3.4.2, 3.5.0, 3.5.1, and 3.6.0. + They are to be considered locked or closed. You can not, must not add + any new APIs and use these versions. Most new APIs will use 3.7.0. If + you add a new API appearing in 3.6.2 (and mainline) then you would use + 3.6.2. + ++ Add the symbol version magic for OS X to the declaration. + + following the declaration in glfs.h, add a line like this: + +```C + GFAPI_PUBLIC(glfs_dtrt, 3.7.0) +``` + + The whole thing should look like: + +```C + int glfs_dtrt (const char *volname, void *stuff) __THROW + GFAPI_PUBLIC(glfs_dtrt, 3.7.0); +``` + + The version here must match the version associated with the definition. + ++ Add the new API to the ELF, gnu toolchain link map file, gfapi.map + + Most new public APIs will probably be added to a new section that + looks like this: + +``` + GFAPI_3.7.0 { + global: + glfs_dtrt; + } GFAPI_PRIVATE_3.7.0; +``` + + if you're adding your new API to, e.g. 3.6.2, it'll look like this: + +``` + GFAPI_3.6.2 { + global: + glfs_dtrt; + } GFAPI_3.6.0; +``` + + and you must change the +``` + GFAPI_PRIVATE_3.7.0 { ...} GFAPI_3.6.0; +``` + section to: +``` + GFAPI_PRIVATE_3.7.0 { ...} GFAPI_3.6.2; +``` + ++ Add the new API to the OS X alias list file, gfapi.aliases. + + Most new APIs will use a line that looks like this: + +```C + _pub_glfs_dtrt _glfs_dtrt$GFAPI_3.7.0 +``` + + if you're adding your new API to, e.g. 3.6.2, it'll look like this: + +```C + _pub_glfs_dtrt _glfs_dtrt$GFAPI_3.6.2 +``` + +And that's it. + + +### Adding a private API. + + If you're thinking about adding a private API that isn't declared in +one of the header files, then you should seriously rethink what you're +doing and figure out how to put it in libglusterfs instead. + +If that hasn't convinced you, follow the instructions above, but use the +_PRIVATE versions of macros, symbol versions, and aliases. If you're 1337 +enough to ignore this advice, then you're 1337 enough to figure out how +to do it. + + +## Changing an API. + +### Changing a public API. + + There are two ways an API might change, 1) its signature has changed, or +2) its new functionality or behavior is substantially different than the +old. An APIs signature consists of the function return type, and the number +and/or type of its parameters. E.g. the original API: + +```C + int glfs_dtrt (const char *volname, void *stuff); +``` + +and the changed API: + +```C + void *glfs_dtrt (const char *volname, glfs_t *ctx, void *stuff); +``` + + One way to avoid a change like this, and which is preferable in many +ways, is to leave the legacy glfs_dtrt() function alone, document it as +deprecated, and simply add a new API, e.g. glfs_dtrt2(). Practically +speaking, that's effectively what we'll be doing anyway, the difference +is only that we'll use a versioned symbol to do it. + + On the assumption that adding a new API is undesirable for some reason, +perhaps the use of glfs_gnu() is just so pervasive that we really don't +want to add glfs_gnu2(). + ++ change the declaration in glfs.h: + +```C + glfs_t *glfs_gnu (const char *volname, void *stuff) __THROW + GFAPI_PUBLIC(glfs_gnu, 3.7.0); +```` + +Note that there is only the single, new declaration. + ++ change the old definition of glfs_gnu() in glfs.c: + +```C + struct glfs * + pub_glfs_gnu340 (const char * volname) + { + ... + } + GFAPI_SYMVER_PUBLIC(glfs_gnu340, glfs_gnu, 3.4.0); +``` + ++ create the new definition of glfs_gnu in glfs.c: + +```C + struct glfs * + pub_glfs_gnu (const char * volname, void *stuff) + { + ... + } + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_gnu, 3.7.0); +``` + ++ Add the new API to the ELF, gnu toolchain link map file, gfapi.map + +``` + GFAPI_3.7.0 { + global: + glfs_gnu; + } GFAPI_PRIVATE_3.7.0; +``` + ++ Update the OS X alias list file, gfapi.aliases, for both versions: + +Change the old line: +```C + _pub_glfs_gnu _glfs_gnu$GFAPI_3.4.0 +``` +to: +```C + _pub_glfs_gnu340 _glfs_gnu$GFAPI_3.4.0 +``` + +Add a new line: +```C + _pub_glfs_gnu _glfs_gnu$GFAPI_3.7.0 +``` + ++ Lastly, change all gfapi internal calls glfs_gnu to the new API. + diff --git a/doc/developer-guide/identifying-resource-leaks.md b/doc/developer-guide/identifying-resource-leaks.md new file mode 100644 index 00000000000..950cae79b0a --- /dev/null +++ b/doc/developer-guide/identifying-resource-leaks.md @@ -0,0 +1,200 @@ +# Identifying Resource Leaks + +Like most other pieces of software, GlusterFS is not perfect in how it manages +its resources like memory, threads and the like. Gluster developers try hard to +prevent leaking resources but releasing and unallocating the used structures. +Unfortunately every now and then some resource leaks are unintentionally added. + +This document tries to explain a few helpful tricks to identify resource leaks +so that they can be addressed. + + +## Debug Builds + +There are certain techniques used in GlusterFS that make it difficult to use +tools like Valgrind for memory leak detection. There are some build options +that make it more practical to use Valgrind and other tools. When running +Valgrind, it is important to have GlusterFS builds that contain the +debuginfo/symbols. Some distributions (try to) strip the debuginfo to get +smaller executables. Fedora and RHEL based distributions have sub-packages +called ...-debuginfo that need to be installed for symbol resolving. + + +### Memory Pools + +By using memory pools, there are no allocation/freeing of single structures +needed. This improves performance, but also makes it impossible to track the +allocation and freeing of srtuctures. + +It is possible to disable the use of memory pools, and use standard `malloc()` +and `free()` functions provided by the C library. Valgrind is then able to +track the allocated areas and verify if they have been free'd. In order to +disable memory pools, the Gluster sources needs to be configured with the +`--enable-debug` option: + +```shell +./configure --enable-debug +``` + +When building RPMs, the `.spec` handles the `--with=debug` option too: + +```shell +make dist +rpmbuild -ta --with=debug glusterfs-....tar.gz +``` + +### Dynamically Loaded xlators + +Valgrind tracks the call chain of functions that do memory allocations. The +addresses of the functions are stored and before Valgrind exits the addresses +are resolved into human readable function names and offsets (line numbers in +source files). Because Gluster loads xlators dynamically, and unloads then +before exiting, Valgrind is not able to resolve the function addresses into +symbols anymore. Whenever this happend, Valgrind shows `???` in the output, +like + +``` + ==25170== 344 bytes in 1 blocks are definitely lost in loss record 233 of 324 + ==25170== at 0x4C29975: calloc (vg_replace_malloc.c:711) + ==25170== by 0x52C7C0B: __gf_calloc (mem-pool.c:117) + ==25170== by 0x12B0638A: ??? + ==25170== by 0x528FCE6: __xlator_init (xlator.c:472) + ==25170== by 0x528FE16: xlator_init (xlator.c:498) + ... +``` + +These `???` can be prevented by not calling `dlclose()` for unloading the +xlator. This will cause a small leak of the handle that was returned with +`dlopen()`, but for improved debugging this can be acceptible. For this and +other Valgrind features, a `--enable-valgrind` option is available to +`./configure`. When GlusterFS is built with this option, Valgrind will be able +to resolve the symbol names of the functions that do memory allocations inside +xlators. + +```shell +./configure --enable-valgrind +``` + +When building RPMs, the `.spec` handles the `--with=valgrind` option too: + +```shell +make dist +rpmbuild -ta --with=valgrind glusterfs-....tar.gz +``` + +## Running Valgrind against a single xlator + +Debugging a single xlator is not trivial. But there are some tools to make it +easier. The `sink` xlator does not do any memory allocations itself, but +contains just enough functionality to mount a volume with only the `sink` +xlator. There is a little gfapi application under `tests/basic/gfapi/` in the +GlusterFS sources that can be used to run only gfapi and the core GlusterFS +infrastructure with the `sink` xlator. By extending the `.vol` file to load +more xlators, each xlator can be debugged pretty much separately (as long as +the xlators have no dependencies on each other). A basic Valgrind run with the +suitable configure options looks like this: + +```shell +./autogen.sh +./configure --enable-debug --enable-valgrind +make && make install +cd tests/basic/gfapi/ +make gfapi-load-volfile +valgrind ./gfapi-load-volfile sink.vol +``` + +Combined with other very useful options to Valgrind, the following execution +shows many more useful details: + +```shell +valgrind \ + --fullpath-after= --leak-check=full --show-leak-kinds=all \ + ./gfapi-load-volfile sink.vol +``` + +Note that the `--fullpath-after=` option is left empty, this makes Valgrind +print the full path and filename that contains the functions: + +``` +==2450== 80 bytes in 1 blocks are definitely lost in loss record 8 of 60 +==2450== at 0x4C29975: calloc (/builddir/build/BUILD/valgrind-3.11.0/coregrind/m_replacemalloc/vg_replace_malloc.c:711) +==2450== by 0x52C6F73: __gf_calloc (/usr/src/debug/glusterfs-3.11dev/libglusterfs/src/mem-pool.c:117) +==2450== by 0x12F10CDA: init (/usr/src/debug/glusterfs-3.11dev/xlators/meta/src/meta.c:231) +==2450== by 0x528EFD5: __xlator_init (/usr/src/debug/glusterfs-3.11dev/libglusterfs/src/xlator.c:472) +==2450== by 0x528F105: xlator_init (/usr/src/debug/glusterfs-3.11dev/libglusterfs/src/xlator.c:498) +==2450== by 0x52D9D8B: glusterfs_graph_init (/usr/src/debug/glusterfs-3.11dev/libglusterfs/src/graph.c:321) +... +``` + +In the above example, the `init` function in `xlators/meta/src/meta.c` does a +memory allocation on line 231. This memory is never free'd again, and hence +Valgrind logs this call stack. When looking in the code, it seems that the +allocation of `priv` is assigned to the `this->private` member of the +`xlator_t` structure. Because the allocation is done in `init()`, free'ing is +expected to happen in `fini()`. Both functions are shown below, with the +inclusion of the empty `fini()`: + + +``` +226 int +227 init (xlator_t *this) +228 { +229 meta_priv_t *priv = NULL; +230 +231 priv = GF_CALLOC (sizeof(*priv), 1, gf_meta_mt_priv_t); +232 if (!priv) +233 return -1; +234 +235 GF_OPTION_INIT ("meta-dir-name", priv->meta_dir_name, str, out); +236 +237 this->private = priv; +238 out: +239 return 0; +240 } +241 +242 +243 int +244 fini (xlator_t *this) +245 { +246 return 0; +247 } +``` + +In this case, the resource leak can be addressed by adding a single line to the +`fini()` function: + +``` +243 int +244 fini (xlator_t *this) +245 { +246 GF_FREE (this->private); +247 return 0; +248 } +``` + +Running the same Valgrind command and comparing the output will show that the +memory leak in `xlators/meta/src/meta.c:init` is not reported anymore. + +### Running DRD, the Valgrind thread error detector + +When configuring GlusterFS with: + +```shell +./configure --enable-valgrind +``` + +the default Valgrind tool (Memcheck) is enabled. But it's also possble to select +one of Memcheck or DRD by using: + +```shell +./configure --enable-valgrind=memcheck +``` + +or: + +```shell +./configure --enable-valgrind=drd +``` + +respectively. When using DRD, it's recommended to consult +https://valgrind.org/docs/manual/drd-manual.html before running. diff --git a/doc/developer-guide/logging-guidelines.md b/doc/developer-guide/logging-guidelines.md new file mode 100644 index 00000000000..0e6b2588535 --- /dev/null +++ b/doc/developer-guide/logging-guidelines.md @@ -0,0 +1,132 @@ +Guidelines on using the logging framework within a component +============================================================ +Gluster library libglusterfs.so provides message logging abstractions that +are intended to be used across all code/components within gluster. + +There could be potentially 2 major cases how the logging infrastructure is +used, + - A new gluster service daemon or end point is created + - The service daemon infrastructure itself initlializes the logging + infrastructure (i.e calling gf_log_init and related set functions) + - See, glusterfsd.c:logging_init + - Alternatively there could be a case where an end point service (say + gfapi) may need to do the required initialization + - This document does not (yet?) cover guidelines for these cases. Best + bet would be to look at code in glusterfsd.c:logging_init (or equivalent) + in case a need arises and you reach this document. + - A new xlator or subcomponent is written as a part of the stack + - Primarily in this case, the consumer of the logging APIs would only + invoke an API to *log* a particular message at a certain severity + - This document elaborates on this use of the message logging framework + in this context + +There are 2 interfaces provided to log messages, +1. The older gf_log* interface +2. The newer gf_msg* interface + +1. Older _to_be_deprecated_ gf_log* interface + - Not much documentation is provided for this interface here, as these are + meant to be deprecated and all code should be moved to the newer gf_msg* + interface + +2. New gf_msg* interface + - The set of interfaces provided by gf_msg are, + - NOTE: It is best to consult logging.h for the latest interfaces, as + this document may get out of sync with the code + + *gf_msg(dom, levl, errnum, msgid, fmt...)* + - Used predominantly to log a message above TRACE and DEBUG levels + - See further guidelines below + + *gf_msg_debug(dom, errnum, fmt...)* + *gf_msg_trace(dom, errnum, fmt...)* + - Above are handy shortcuts for TRACE and DEBUG level messages + - See further guidelines below + + *gf_msg_callingfn(dom, levl, errnum, msgid, fmt...)* + - Useful function when a backtrace to detect calling routines that + reached this execution point needs to be logged in addition to the + message + - This is very handy for framework libraries or code, as there could + be many callers to the same, and the real failure would need the call + stack to determine who the caller actually was + - A good example is the dict interfaces using this function to log who + called, when a particular error/warning needs to be displayed + - See further guidelines below + + *gf_msg_plain(levl, fmt...)* + *gf_msg_plain_nomem(levl, msg)* + *gf_msg_vplain(levl, fmt, va)* + *gf_msg_backtrace_nomem* + - The above interfaces are provided to log messages without any typical + headers (like the time stamp, dom, errnum etc.). The primary users of + the above interfaces are, when printing the final graph, or printing + the configuration when a process is about dump core or abort, or + printing the backtrace when a process receives a critical signal + - These interfaces should not be used outside the scope of the users + above, unless you know what you are doing + + *gf_msg_nomem(dom, levl, size)* + - Very crisp messages, throwing out file, function, line numbers, in + addition to the passed in size + - These are used in the memory allocation abstractions interfaces in + gluster, when the allocation fails (hence a no-mem log message, so that + further allocation is not attempted by the logging infrastructure) + - If you are contemplating using these, then you know why and how + + - Guidelines for the various arguments to the interfaces + **dom** + - The domain from which this message appears, IOW for xlators it should + be the name of the xlator (as in this->name) + + - The intention of this string is to distinguish from which + component/xlator the message is being printed + + - This information can also be gleaned from the FILE:LINE:FUNCTION + information printed in the message anyway, but is retained to provide + backward compatability to the messages as seen by admins earlier + + **levl** + - Consult logging.h:gf_loglevel_t for logging levels (they pretty much + map to syslog levels) + + **errnum** + - errno should be passed in here, if available, 0 otherwise. This auto + enables the logging infrastructure to print (man 3) strerror form of the + same at the end of the message in a consistent format + + - If any message is already adding the strerror as a parameter to the + message, it is suggested/encouraged to remove the same and pass it as + errnum + + - The intention is that, if all messages did this using errnum and not + as a part of their own argument list, the output would look consistent + for the admin and cross component developers when reading logs + + **msgid** + - This is a unique message ID per message (which now is more a message + ID per group of messages in the implementation) + + - Rules for generating this ID can be found in dht-messages.h (it used + to be template-common-messages.h, but that template is not updated, + this comment should be changed once that is done) and glfs-message-id.h + + - Every message that is *above* TRACE and DEBUG should get a message + ID, as this helps generating message catalogs that can help admins to + understand the context of messages better. Another intention is that + automated message parsers could detect a class of message IDs and send + out notifications on the same, rather than parse the message string + itself (which if it changes, the input to the parser has to change, etc. + and hence is better to retain message IDs) + + - Ok so if intention is not yet clear, look at journald MESSAGE ID + motivation, as that coupled with ident/dom above is expected to provide + us with similar advantages + + - Bottomline: Every message gets its own ID, in case a message is + *not* DEBUG or TRACE and still is developer centric, a generic message + ID per component *maybe* assigned to the same to provide ease of use + of the API + + **fmt** + - As in format argument of (man 3) printf diff --git a/doc/developer-guide/network_compression.md b/doc/developer-guide/network_compression.md new file mode 100644 index 00000000000..1222a765276 --- /dev/null +++ b/doc/developer-guide/network_compression.md @@ -0,0 +1,71 @@ +# On-Wire Compression + Decompression + +The 'compression translator' compresses and decompresses data in-flight +between client and bricks. + +### Working +When a writev call occurs, the client compresses the data before sending it to +brick. On the brick, compressed data is decompressed. Similarly, when a readv +call occurs, the brick compresses the data before sending it to client. On the +client, the compressed data is decompressed. Thus, the amount of data sent over +the wire is minimized. Compression/Decompression is done using Zlib library. + +During normal operation, this is the format of data sent over wire: + +~~~ +<compressed-data> + trailer(8 bytes) +~~~ + +The trailer contains the CRC32 checksum and length of original uncompressed +data. This is used for validation. + +### Usage + +Turning on compression xlator: + +~~~ +gluster volume set <vol_name> network.compression on +~~~ + +### Configurable parameters (optional) + +**Compression level** +~~~ +gluster volume set <vol_name> network.compression.compression-level 8 +~~~ + +~~~ + 0 : no compression + 1 : best speed + 9 : best compression +-1 : default compression +~~~ + +**Minimum file size** + +~~~ +gluster volume set <vol_name> network.compression.min-size 50 +~~~ + +Data is compressed only when its size exceeds the above value in bytes. + +**Other paramaters** + +Other less frequently used parameters include `network.compression.mem-level` +and `network.compression.window-size`. More details can about these options +can be found by running `gluster volume set help` command. + +### Known Issues and Limitations + +* Compression translator cannot work with striped volumes. +* Mount point hangs when writing a file with write-behind xlator turned on. To +overcome this, turn off `performance.write-behind` entirely OR +set`performance.strict-write-ordering` to on. +* For glusterfs versions <= 3.5, compression traslator can ONLY work with pure +distribute volumes. This limitation is caused by AFR not being able to +propagate xdata. This issue has been fixed in glusterfs versions > 3.5 + +### TODO +Although zlib offers high compression ratio, it is very slow. We can make the +translator pluggable to add support for other compression methods such as +[lz4 compression](https://code.google.com/p/lz4/) diff --git a/doc/developer-guide/options-to-contribute.md b/doc/developer-guide/options-to-contribute.md new file mode 100644 index 00000000000..3f0d84e7645 --- /dev/null +++ b/doc/developer-guide/options-to-contribute.md @@ -0,0 +1,212 @@ +# A guide for contributors + +While you have gone through 'how to contribute' guides, if you are +not sure what to work on, but really want to help the project, you +have now landed on the right document :-) + +### Basic + +Instead of planning to fix **all** the below issues in one patch, +we recommend you to have a a constant, continuous flow of improvements +for the project. We recommend you to pick 1 file (or just few files) at +a time to address below issues. +Pick any `.c` (or `.h`) file, and you can send a patch which fixes **any** +of the below themes. Ideally, fix all such occurrences in the file, even +though, the reviewers would review even a single line change patch +from you. + +1. Check for variable definitions, and if there is an array definition, +which is very large at the top of the function, see if you can re-scope +the variable to relevant sections (if it helps). + +Most of the time, some of these arrays may be used for 'error' handling, +and it is possible to use them only in that scope. + +Reference: https://review.gluster.org/20846/ + + +2. Check for complete string initialization at the beginning of a function. +Ideally, there is no reason to initialize a string. Fix it across the file. + +Example: + +`char new_path_name[PATH_MAX] = {0};` to `char new_path_name[PATH_MAX];` + + +3. Change `calloc()` to `malloc()` wherever it makes sense. + +In a case of allocating a structures, where you expect certain (or most of) +variables to be 0 (or NULL), it makes sense to use calloc(). But otherwise, +there is an extra cost to `memset()` the whole object after allocating it. +While it is not a significant improvement in performance, code which gets +hit 1000s of times in a second, it would add some value. + +Reference: https://review.gluster.org/20878/ + + +4. You can consider using `snprintf()`, instead of `strncpy()` while dealing +with strings. + +strncpy() won't null terminate if the dest buffer isn't big enough; snprintf() +does. While most of the string operations in the code is on array, and larger +size than required, strncpy() does an extra copy of 0s at the end of +string till the size of the array. It makes sense to use `snprintf()`, +which doesn't suffer from that behavior. + +Also check the return value from snprintf() for buffer overflow and handle +accordingly + +Reference: https://review.gluster.org/20925/ + + +5. Now, pick a `.h` file, and see if a structure is very large, and see +if re-aligning them as per [coding-standard](./coding-standard.md) gives any size benefit, +if yes, go ahead and change it. Make sure you check all the structures +in the file for similar pattern. + +Reference: [Check this section](https://github.com/gluster/glusterfs/blob/master/doc/developer-guide/coding-standard.md#structure-members-should-be-aligned-based-on-the-padding-requirements + + +### If you are up for more :-) + +Good progress! Glad you are interested to know more. We are surely interested +in next level of contributions from you! + +#### Coverity + +Visit [Coverity Dashboard](https://scan.coverity.com/projects/gluster-glusterfs?tab=overview). + +Now, if the number of defect is not 0, you have an opportunity to contribute. + +You get all the detail on why the particular defect is mentioned there, and +most probable hint on how to fix it. Do it! + +Reference: https://review.gluster.org/21394/ + +Use the same reference Id (789278) as the patch, so we can capture it is in +single bugzilla. + +#### Clang-Scan + +Clang-Scan is a tool which scans the .c files and reports the possible issues, +similar to coverity, but a different tool. Over the years we have seen, they +both report very different set of issues, and hence there is a value in fixing it. + +GlusterFS project gets tested with clang-scan job every night, and the report is +posted in the [job details page](https://build.gluster.org/job/clang-scan/lastCompletedBuild/clangScanBuildBugs/). +As long as the number is not 0 in the report here, you have an opportunity to +contribute! Similar to coverity dashboard, click on 'Details' to find out the +reason behind that report, and send a patch. + +Reference: https://review.gluster.org/21025 + +Again, you can use reference Id (1622665) for these patches! + + +### I am good with programming, I would like to do more than above! + +#### Locked regions / Critical sections + +In the file you open, see if the lock is taken only to increment or decrement +a flag, counter etc. If yes, then recommend you to convert it to ATOMIC locks. +It is simple activity, but, if you know programing, you would know the benefit +here. + +NOTE: There may not always a possibility to do this! You may have to check +with developers first before going ahead. + +Reference: https://review.gluster.org/21221/ + + +#### ASan (address sanitizer) + +[The job](https://build.gluster.org/job/asan/) runs regression with asan builds, +and you can also run glusterfs with asan on your workload to identify the leaks. +If there are any leaks reported, feel free to check it, and send us patch. + +You can also run `valgrind` and let us know what it reports. + +Reference: https://review.gluster.org/21397 + + +#### Porting to different architecture + +This is something which we are not focusing right now, happy to collaborate! + +Reference: https://review.gluster.org/21276 + + +#### Fix 'TODO/FIXME' in codebase + +There are few cases of pending features, or pending validations, which are +pending from sometime. You can pick them in the given file, and choose to +fix it. + + +### I don't know C, but I am interested to contribute in some way! + +You are most welcome! Our community is open for your contribution! First thing +which comes to our mind is **documentation**. Next is, **testing** or validation. + +If you have some hardware, and want to run some performance comparisons with +different version, or options, and help us to tune better is also a great help. + + +#### Documentation + +1. We have some documentation in [glusterfs repo](../), go through these, and +see if you can help us to keep up-to-date. + +2. The https://docs.gluster.org is powered by https://github.com/gluster/glusterdocs +repo. You can check out the repo, and help in keeping that up-to-date. + +3. [Our website](https://gluster.org) is maintained by https://github.com/gluster/glusterweb +repo. Help us to keep this up-to-date, and add content there. + +4. Write blogs about Gluster, and your experience, and make world know little +more about Gluster, and your use-case, and how it helped to solve the problem. + + +#### Testing + +1. There is a regression test suite in glusterfs, which runs with every patch, and is +triggered by just running `./run-tests.sh` from the root of the project repo. + +You can add more test case to match your use-case, and send it as a patch, so you +can make sure all future patches in glusterfs would keep your usecase intact. + +2. [Glusto-Tests](https://github.com/gluster/glusto-tests): This is another testing +framework written for gluster, and makes use of clustered setup to test different +use-cases, and helps to validate many bugs. + + +#### Ansible + +Gluster Organization has rich set of ansible roles, which are actively maintained. +Feel free to check them out here - https://github.com/gluster/gluster-ansible + + +#### Monitoring + +We have prometheus repo, and are actively working on adding more metrics. Add what +you need @ https://github.com/gluster/gluster-prometheus + + +#### Health-Report + +This is a project, where at any given point in time, you want to run some set of +commands locally, and get an output to analyze the status, it can be added. +Contribute @ https://github.com/gluster/gluster-health-report + + +### All these C/bash/python is old-school, I want something in containers. + +We have something for you too :-) + +Please visit our https://github.com/gluster/gcs repo for checking how you can help, +and how gluster can help you in container world. + + +### Note + +For any queries, best way is to contact us through mailing-list, <mailto:gluster-devel@gluster.org> diff --git a/doc/developer-guide/posix.md b/doc/developer-guide/posix.md new file mode 100644 index 00000000000..84c813e55a2 --- /dev/null +++ b/doc/developer-guide/posix.md @@ -0,0 +1,59 @@ +storage/posix translator +======================== + +Notes +----- + +### `SET_FS_ID` + +This is so that all filesystem checks are done with the user's +uid/gid and not GlusterFS's uid/gid. + +### `MAKE_REAL_PATH` + +This macro concatenates the base directory of the posix volume +('option directory') with the given path. + +### `need_xattr` in lookup + +If this flag is passed, lookup returns a xattr dictionary that contains +the file's create time, the file's contents, and the version number +of the file. + +This is a hack to increase small file performance. If an application +wants to read a small file, it can finish its job with just a lookup +call instead of a lookup followed by read. + +### `getdents`/`setdents` + +These are used by unify to set and get directory entries. + +### `ALIGN_BUF` + +Macro to align an address to a page boundary (4K). + +### `priv->export_statfs` + +In some cases, two exported volumes may reside on the same +partition on the server. Sending statvfs info for both +the volumes will lead to erroneous df output at the client, +since free space on the partition will be counted twice. + +In such cases, user can disable exporting statvfs info +on one of the volumes by setting this option. + +### `xattrop` + +This fop is used by replicate to set version numbers on files. + +### `getxattr`/`setxattr` hack to read/write files + +A key, `GLUSTERFS_FILE_CONTENT_STRING`, is handled in a special way by +`getxattr`/`setxattr`. A getxattr with the key will return the entire +content of the file as the value. A `setxattr` with the key will write +the value as the entire content of the file. + +### `posix_checksum` + +This calculates a simple XOR checksum on all entry names in a +directory that is used by unify to compare directory contents. diff --git a/doc/rpc-for-glusterfs.changes-done.txt b/doc/developer-guide/rpc-for-glusterfs.changes-done.txt index 6bbbca78826..6bbbca78826 100644 --- a/doc/rpc-for-glusterfs.changes-done.txt +++ b/doc/developer-guide/rpc-for-glusterfs.changes-done.txt diff --git a/doc/developer-guide/rpc-for-glusterfs.new-versions.md b/doc/developer-guide/rpc-for-glusterfs.new-versions.md new file mode 100644 index 00000000000..e3da5efa4a2 --- /dev/null +++ b/doc/developer-guide/rpc-for-glusterfs.new-versions.md @@ -0,0 +1,32 @@ +# GlusterFS RPC program versions + +## Compatibility + +RPC layer of glusterfs is implemented with possible changes over the protocol layers in mind. If there are any changes in the FOPs from what is assumed to be client side, and whats in serverside, they are to be added as a separate program table. + +### Program tables and Versions + +A given RPC program has a specific Task, and Version along with actors belonging to the program. In any of the programs, if a new actor is added, it is very important to define one more program with different version, and then keep both, if both are supported. Or else, it is important to handle the 'handshake' properly. + +#### Server details + +More info on RPC program is at `rpc/rpc-lib/src/rpcsvc.h` and check for structure `rpcsvc_actor_t` and `struct rpcsvc_program`. For usage, check `xlators/protocol/server/src/server-rpc-fops.c` + +#### Client details + +For details on client structures check `rpc/rpc-lib/src/rpc-clnt.h` for `rpc_clnt_procedure_t` and `rpc_clnt_program_t`. For usage, check `xlators/protocol/client/src/client-rpc-fops.c` + +## Protocol + +A protocol is what is agreed between two parties. In glusterfs, a RPC protocol is defined as .x file, which then gets converted to .c/.h file using `rpcgen`. There are different protocols defined for communication between `xlators/mgmt/glusterd <==> glusterfsd`, `gluster CLI <==> glusterd`, and `client-protocol <==> server-protocol` + +Once a protocol is defined and a release is made with that protocol, make sure no one changes it. Any edits to a given structure there should be a new version of the structure, and also it should get used in new actor, and thus new program version. + +## Server and Client Handshake + +When a client succeeds to establish a connect (it can be any transport, socket, ib-verbs or unix), client sends a dump (GF_DUMP_DUMP) request to server, which will respond back with all the supported versions of the server RPC (the supported programs which are registered with `rpcsvc_program_register()`). + +A client which expects certain programs to be present in server, it should be taking care of looking for it in the handshake methods, and take appropriate action depending on what to do next. In general a compatibility issue should be handled at handshake level itself, thus we can clearly let user/admin know of any 'in-compatibilities'. +As a developer of GlusterFS protocol layer, one just has to make sure *never to make changes to existing program structures*, but they have to add new programs if required. New programs can have the same actors as present in existing, and also little more. Or it can even have same actor behave differently, take different parameter. + +If this is followed properly, there would be smooth upgrade / downgrade of versions. If not, technically, it is 100% guarantee of getting compatibility related issues. diff --git a/doc/developer-guide/syncop.md b/doc/developer-guide/syncop.md new file mode 100644 index 00000000000..bcc8bd08e01 --- /dev/null +++ b/doc/developer-guide/syncop.md @@ -0,0 +1,72 @@ +# syncop framework +A coroutines-based, cooperative multi-tasking framework. + +## Topics + +- Glossary +- Lifecycle of a synctask +- Existing usage + + +## Glossary + +### syncenv + +syncenv is an object that provides access to a pool of worker threads. +synctasks execute in a syncenv. + +### synctask + +synctask can be informally defined as a pair of function pointers, namely _the +call_ and _the callback_ (see syncop.h for more details). + + synctask_fn_t - 'the call' + synctask_cbk_t - 'the callback' + +synctask has two modes of operation, + +1. The calling thread waits for the synctask to complete. +2. The calling thread schedules the synctask and continues. + +synctask guarantees that the callback is called _after_ the call completes. + +### Lifecycle of a synctask + +A synctask could go into the following stages while in execution. + +- CREATED - On calling synctask_create/synctask_new. + +- RUNNABLE - synctask is queued in env->runq. + +- RUNNING - When one of syncenv's worker threads calls synctask_switch_to. + +- WAITING - When a synctask calls synctask_yield. + +- DONE - When a synctask has run to completion. + + + +-------------------------------+ + | CREATED | + +-------------------------------+ + | + | synctask_new/synctask_create + v + +-------------------------------+ + | RUNNABLE (in env->runq) | <+ + +-------------------------------+ | + | | + | synctask_switch_to | + v | + +------+ on task completion +-------------------------------+ | + | DONE | <-------------------- | RUNNING | | synctask_wake/wake + +------+ +-------------------------------+ | + | | + | synctask_yield/yield | + v | + +-------------------------------+ | + | WAITING (in env->waitq) | -+ + +-------------------------------+ + +Note: A synctask is not guaranteed to run on the same thread throughout its +lifetime. Every time a synctask yields, it is possible for it to run on a +different thread. diff --git a/doc/developer-guide/thread-naming.md b/doc/developer-guide/thread-naming.md new file mode 100644 index 00000000000..513140d4437 --- /dev/null +++ b/doc/developer-guide/thread-naming.md @@ -0,0 +1,104 @@ +Thread Naming +================ +Gluster processes spawn many threads; some threads are created by libglusterfs +library, while others are created by xlators. When gfapi library is used in an +application, some threads belong to the application and some are spawned by +gluster libraries. We also have features where n number of threads are spawned +to act as worker threads for same operation. + +In all the above cases, it is useful to be able to determine the list of threads +that exist in runtime. Naming threads when you create them is the easiest way to +provide that information to kernel so that it can then be queried by any means. + +How to name threads +------------------- +We have two wrapper functions in libglusterfs for creating threads. They take +name as an argument and set thread name after its creation. + +```C +gf_thread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg, const char *name) +``` + +```C +gf_thread_create_detached (pthread_t *thread, + void *(*start_routine)(void *), void *arg, + const char *name) +``` + +As max name length for a thread in POSIX is only 16 characters including the +'\0' character, you have to be a little creative with naming. Also, it is +important that all Gluster threads have common prefix. Considering these +conditions, we have "glfs_" as prefix for all the threads created by these +wrapper functions. It is responsibility of the owner of thread to provide the +suffix part of the name. It does not have to be a descriptive name, as it has +only 10 letters to work with. However, it should be unique enough such that it +can be matched with a table which describes it. + +If n number of threads are spwaned to perform same function, it is must that the +threads are numbered. + +Table of thread names +--------------------- +Thread names don't have to be a descriptive; however, it should be unique enough +such that it can be matched with a table below without ambiguity. + +- bdaio - block device aio +- brfsscan - bit rot fs scanner +- brhevent - bit rot event handler +- brmon - bit rot monitor +- brosign - bit rot one shot signer +- brpobj - bit rot object processor +- brsproc - bit rot scrubber +- brssign - bit rot stub signer +- brswrker - bit rot worker +- clogc - changelog consumer +- clogcbki - changelog callback invoker +- clogd - changelog dispatcher +- clogecon - changelog reverse connection +- clogfsyn - changelog fsync +- cloghcon - changelog history consumer +- clogjan - changelog janitor +- clogpoll - changelog poller +- clogproc - changelog process +- clogro - changelog rollover +- ctrcomp - change time recorder compaction +- dhtdf - dht defrag task +- dhtdg - dht defrag start +- dhtfcnt - dht rebalance file counter +- ecshd - ec heal daemon +- epollN - epoll thread +- fdlwrker - fdl worker +- fusenoti - fuse notify +- fuseproc - fuse main thread +- gdhooks - glusterd hooks +- glfspoll - gfapi poller thread +- idxwrker - index worker +- iosdump - io stats dump +- iotwr - io thread worker +- jbrflush - jbr flush +- leasercl - lease recall +- memsweep - sweeper thread for mem pools +- nfsauth - nfs auth +- nfsnsm - nfs nsm +- nfsudp - nfs udp mount +- nlmmon - nfs nlm/nsm mon +- posixaio - posix aio +- posixfsy - posix fsync +- posixhc - posix heal +- posixjan - posix janitor +- posixrsv - posix reserve +- quiesce - quiesce dequeue +- rdmaAsyn - rdma async event handler +- rdmaehan - rdma completion handler +- rdmarcom - rdma receive completion handler +- rdmascom - rdma send completion handler +- rpcsvcrh - rpcsvc request handler +- scleanup - socket cleanup +- shdheal - self heal daemon +- sigwait - glusterfsd sigwaiter +- spoller - socket poller +- sprocN - syncop worker thread +- tbfclock - token bucket filter token generator thread +- timer - timer thread +- upreaper - upcall reaper diff --git a/doc/developer-guide/translator-development.md b/doc/developer-guide/translator-development.md new file mode 100644 index 00000000000..f75935519f6 --- /dev/null +++ b/doc/developer-guide/translator-development.md @@ -0,0 +1,683 @@ +Translator development +====================== + +Setting the Stage +----------------- + +This is the first post in a series that will explain some of the details of +writing a GlusterFS translator, using some actual code to illustrate. + +Before we begin, a word about environments. GlusterFS is over 300K lines of +code spread across a few hundred files. That's no Linux kernel or anything, but + you're still going to be navigating through a lot of code in every +code-editing session, so some kind of cross-referencing is *essential*. I use +cscope with the vim bindings, and if I couldn't do Crtl+G and such to jump +between definitions all the time my productivity would be cut in half. You may +prefer different tools, but as I go through these examples you'll need +something functionally similar to follow on. OK, on with the show. + +The first thing you need to know is that translators are not just bags of +functions and variables. They need to have a very definite internal structure +so that the translator-loading code can figure out where all the pieces are. +The way it does this is to use dlsym to look for specific names within your +shared-object file, as follow (from `xlator.c`): + +``` +if (!(xl->fops = dlsym (handle, "fops"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fops) on %s", + dlerror ()); + goto out; +} + +if (!(xl->cbks = dlsym (handle, "cbks"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(cbks) on %s", + dlerror ()); + goto out; +} + +if (!(xl->init = dlsym (handle, "init"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(init) on %s", + dlerror ()); + goto out; +} + +if (!(xl->fini = dlsym (handle, "fini"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fini) on %s", + dlerror ()); + goto out; +} +``` + +In this example, `xl` is a pointer to the in-memory object for the translator +we're loading. As you can see, it's looking up various symbols *by name* in the + shared object it just loaded, and storing pointers to those symbols. Some of +them (e.g. init) are functions, while others (e.g. fops) are dispatch tables +containing pointers to many functions. Together, these make up the translator's + public interface. + +Most of this glue or boilerplate can easily be found at the bottom of one of +the source files that make up each translator. We're going to use the `rot-13` +translator just for fun, so in this case you'd look in `rot-13.c` to see this: + +``` +struct xlator_fops fops = { + .readv = rot13_readv, + .writev = rot13_writev +}; + +struct xlator_cbks cbks = { +}; + +struct volume_options options[] = { +{ .key = {"encrypt-write"}, + .type = GF_OPTION_TYPE_BOOL +}, +{ .key = {"decrypt-read"}, + .type = GF_OPTION_TYPE_BOOL +}, +{ .key = {NULL} }, +}; +``` + +The `fops` table, defined in `xlator.h`, is one of the most important pieces. +This table contains a pointer to each of the filesystem functions that your +translator might implement -- `open`, `read`, `stat`, `chmod`, and so on. There +are 82 such functions in all, but don't worry; any that you don't specify here +will be see as null and filled with defaults from `defaults.c` when your +translator is loaded. In this particular example, since `rot-13` is an +exceptionally simple translator, we only fill in two entries for `readv` and +`writev`. + +There are actually two other tables, also required to have predefined names, +that are also used to find translator functions: `cbks` (which is empty in this + snippet) and `dumpops` (which is missing entirely). The first of these specify + entry points for when inodes are forgotten or file descriptors are released. +In other words, they're destructors for objects in which your translator might + have an interest. Mostly you can ignore them, because the default behavior +handles even the simpler cases of translator-specific inode/fd context +automatically. However, if the context you attach is a complex structure +requiring complex cleanup, you'll need to supply these functions. As for +dumpops, that's just used if you want to provide functions to pretty-print +various structures in logs. I've never used it myself, though I probably +should. What's noteworthy here is that we don't even define dumpops. That's +because all of the functions that might use these dispatch functions will check + for `xl->dumpops` being `NULL` before calling through it. This is in sharp +contrast to the behavior for `fops` and `cbks`, which *must* be present. If +they're not, translator loading will fail because these pointers are not +checked every time and if they're `NULL` then we'll segfault. That's why we +provide an empty definition for cbks; it's OK for the individual function +pointers to be NULL, but not for the whole table to be absent. + +The last piece I'll cover today is options. As you can see, this is a table of +translator-specific option names and some information about their types. +GlusterFS actually provides a pretty rich set of types (`volume_option_type_t` +in `options.`h) which includes paths, translator names, percentages, and times +in addition to the obvious integers and strings. Also, the `volume_option_t` +structure can include information about alternate names, min/max/default +values, enumerated string values, and descriptions. We don't see any of these +here, so let's take a quick look at some more complex examples from afr.c and +then come back to `rot-13`. + +``` +{ .key = {"data-self-heal-algorithm"}, + .type = GF_OPTION_TYPE_STR, + .default_value = "", + .description = "Select between \"full\", \"diff\". The " + "\"full\" algorithm copies the entire file from " + "source to sink. The \"diff\" algorithm copies to " + "sink only those blocks whose checksums don't match " + "with those of source.", + .value = { "diff", "full", "" } +}, +{ .key = {"data-self-heal-window-size"}, + .type = GF_OPTION_TYPE_INT, + .min = 1, + .max = 1024, + .default_value = "1", + .description = "Maximum number blocks per file for which " + "self-heal process would be applied simultaneously." +}, +``` + +When your translator is loaded, all of this information is used to parse the +options actually provided in the volfile, and then the result is turned into a +dictionary and stored as `xl->options`. This dictionary is then processed by +your init function, which you can see being looked up in the first code +fragment above. We're only going to look at a small part of the `rot-13`'s +init for now. + +``` +priv->decrypt_read = 1; +priv->encrypt_write = 1; + +data = dict_get (this->options, "encrypt-write"); +if (data) { + if (gf_string2boolean (data->data, &priv->encrypt_write + == -1) { + gf_log (this->name, GF_LOG_ERROR, + "encrypt-write takes only boolean options"); + return -1; + } +} +``` + +What we can see here is that we're setting some defaults in our priv structure, +then looking to see if an `encrypt-write` option was actually provided. If so, +we convert and store it. This is a pretty classic use of dict_get to fetch a +field from a dictionary, and of using one of many conversion functions in +`common-utils.c` to convert `data->data` into something we can use. + +So far we've covered the basic of how a translator gets loaded, how we find its +various parts, and how we process its options. In my next Translator 101 post, +we'll go a little deeper into other things that init and its companion fini +might do, and how some other fields in our `xlator_t` structure (commonly +referred to as this) are commonly used. + +`init`, `fini`, and private context +----------------------------------- + +In the previous Translator 101 post, we looked at some of the dispatch tables +and options processing in a translator. This time we're going to cover the rest + of the "shell" of a translator -- i.e. the other global parts not specific to +handling a particular request. + +Let's start by looking at the relationship between a translator and its shared +library. At a first approximation, this is the relationship between an object +and a class in just about any object-oriented programming language. The class +defines behaviors, but has to be instantiated as an object to have any kind of +existence. In our case the object is an `xlator_t`. Several of these might be +created within the same daemon, sharing all of the same code through init/fini +and dispatch tables, but sharing *no data*. You could implement shared data (as + static variables in your shared libraries) but that's strongly discouraged. +Every function in your shared library will get an `xlator_t` as an argument, +and should use it. This lack of class-level data is one of the points where +the analogy to common OOP systems starts to break down. Another place is the +complete lack of inheritance. Translators inherit behavior (code) from exactly +one shared library -- looked up and loaded using the `type` field in a volfile +`volume ... end-volume` block -- and that's it -- not even single inheritance, +no subclasses or superclasses, no mixins or prototypes, just the relationship +between an object and its class. With that in mind, let's turn to the init +function that we just barely touched on last time. + +``` +int32_t +init (xlator_t *this) +{ + data_t *data = NULL; + rot_13_private_t *priv = NULL; + + if (!this->children || this->children->next) { + gf_log ("rot13", GF_LOG_ERROR, + "FATAL: rot13 should have exactly one child"); + return -1; + } + + if (!this->parents) { + gf_log (this->name, GF_LOG_WARNING, + "dangling volume. check volfile "); + } + + priv = GF_CALLOC (sizeof (rot_13_private_t), 1, 0); + if (!priv) + return -1; +``` + +At the very top, we see the function signature -- we get a pointer to the +`xlator_t` object that we're initializing, and we return an `int32_t` status. +As with most functions in the translator API, this should be zero to indicate +success. In this case it's safe to return -1 for failure, but watch out: in +dispatch-table functions, the return value means the status of the *function +call* rather than the *request*. A request error should be reflected as a +callback with a non-zero `op_re`t value, but the dispatch function itself +should still return zero. In fact, the handling of a non-zero return from a +dispatch function is not all that robust (we recently had a bug report in +HekaFS related to this) so it's something you should probably avoid +altogether. This only underscores the difference between dispatch functions +and `init`/`fini` functions, where non-zero returns *are* expected and handled +logically by aborting the translator setup. We can see that down at the +bottom, where we return -1 to indicate that we couldn't allocate our +private-data area (more about that later). + +The first thing this init function does is check that the translator is being +set up in the right kind of environment. Translators are called by parents and +in turn call children. Some translators are "initial" translators that inject +requests into the system from elsewhere -- e.g. mount/fuse injecting requests +from the kernel, protocol/server injecting requests from the network. Those +translators don't need parents, but `rot-13` does and so we check for that. +Similarly, some translators are "final" translators that (from the perspective +of the current process) terminate requests instead of passing them on -- e.g. +`protocol/client` passing them to another node, `storage/posix` passing them to +a local filesystem. Other translators "multiplex" between multiple children -- + passing each parent request on to one (`cluster/dht`), some +(`cluster/stripe`), or all (`cluster/afr`) of those children. `rot-13` fits +into none of those categories either, so it checks that it has *exactly one* +child. It might be more convenient or robust if translator shared libraries +had standard variables describing these requirements, to be checked in a +consistent way by the translator-loading infrastructure itself instead of by +each separate init function, but this is the way translators work today. + +The last thing we see in this fragment is allocating our private data area. +This can literally be anything we want; the infrastructure just provides the +priv pointer as a convenience but takes no responsibility for how it's used. In + this case we're using `GF_CALLOC` to allocate our own `rot_13_private_t` +structure. This gets us all the benefits of GlusterFS's memory-leak detection +infrastructure, but the way we're calling it is not quite ideal. For one thing, + the first two arguments -- from `calloc(3)` -- are kind of reversed. For +another, notice how the last argument is zero. That can actually be an +enumerated value, to tell the GlusterFS allocator *what* type we're +allocating. This can be very useful information for memory profiling and leak +detection, so it's recommended that you follow the example of any +x`xx-mem-types.h` file elsewhere in the source tree instead of just passing +zero here (even though that works). + +To finish our tour of standard initialization/termination, let's look at the +end of `init` and the beginning of `fini`: + +``` + this->private = priv; + gf_log ("rot13", GF_LOG_DEBUG, "rot13 xlator loaded"); + return 0; +} + +void +fini (xlator_t *this) +{ + rot_13_private_t *priv = this->private; + + if (!priv) + return; + this->private = NULL; + GF_FREE (priv); +``` + +At the end of init we're just storing our private-data pointer in the `priv` +field of our `xlator_t`, then returning zero to indicate that initialization +succeeded. As is usually the case, our fini is even simpler. All it really has +to do is `GF_FREE` our private-data pointer, which we do in a slightly +roundabout way here. Notice how we don't even have a return value here, since +there's nothing obvious and useful that the infrastructure could do if `fini` +failed. + +That's practically everything we need to know to get our translator through +loading, initialization, options processing, and termination. If we had defined + no dispatch functions, we could actually configure a daemon to use our +translator and it would work as a basic pass-through from its parent to a +single child. In the next post I'll cover how to build the translator and +configure a daemon to use it, so that we can actually step through it in a +debugger and see how it all fits together before we actually start adding +functionality. + +This Time For Real +------------------ + +In the first two parts of this series, we learned how to write a basic +translator skeleton that can get through loading, initialization, and option +processing. This time we'll cover how to build that translator, configure a +volume to use it, and run the glusterfs daemon in debug mode. + +Unfortunately, there's not much direct support for writing new translators. You +can check out a GlusterFS tree and splice in your own translator directory, but + that's a bit painful because you'll have to update multiple makefiles plus a +bunch of autoconf garbage. As part of the HekaFS project, I basically reverse +engineered the truly necessary parts of the translator-building process and +then pestered one of the Fedora glusterfs package maintainers (thanks +daMaestro!) to add a `glusterfs-devel` package with the required headers. Since + then the complexity level in the HekaFS tree has crept back up a bit, but I +still remember the simple method and still consider it the easiest way to get +started on a new translator. For the sake of those not using Fedora, I'm going +to describe a method that doesn't depend on that header package. What it does +depend on is a GlusterFS source tree, much as you might have cloned from GitHub + or the Gluster review site. This tree doesn't have to be fully built, but you +do need to run `autogen.sh` and configure in it. Then you can take the +following simple makefile and put it in a directory with your actual source. + +``` +# Change these to match your source code. +TARGET = rot-13.so +OBJECTS = rot-13.o + +# Change these to match your environment. +GLFS_SRC = /srv/glusterfs +GLFS_LIB = /usr/lib64 +HOST_OS = GF_LINUX_HOST_OS + +# You shouldn't need to change anything below here. + +CFLAGS = -fPIC -Wall -O0 -g \ + -DHAVE_CONFIG_H -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE \ + -D$(HOST_OS) -I$(GLFS_SRC) -I$(GLFS_SRC)/contrib/uuid \ + -I$(GLFS_SRC)/libglusterfs/src +LDFLAGS = -shared -nostartfiles -L$(GLFS_LIB) +LIBS = -lglusterfs -lpthread + +$(TARGET): $(OBJECTS) + $(CC) $(OBJECTS) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) +``` + +Yes, it's still Linux-specific. Mea culpa. As you can see, we're sticking with +the `rot-13` example, so you can just copy the files from +`xlators/encryption/rot-13/src` in your GlusterFS tree to follow on. Type +`make` and you should be rewarded with a nice little `.so` file. + +``` +xlator_example$ ls -l rot-13.so +-rwxr-xr-x. 1 jeff jeff 40784 Nov 16 16:41 rot-13.so +``` + +Notice that we've built with optimization level zero and debugging symbols +included, which would not typically be the case for a packaged version of +GlusterFS. Let's put our version of `rot-13.so` into a slightly different file +on our system, so that it doesn't stomp on the installed version (not that +you'd ever want to use that anyway). + +``` +xlator_example# ls /usr/lib64/glusterfs/3git/xlator/encryption/ +crypt.so crypt.so.0 crypt.so.0.0.0 rot-13.so rot-13.so.0 +rot-13.so.0.0.0 +xlator_example# cp rot-13.so \ + /usr/lib64/glusterfs/3git/xlator/encryption/my-rot-13.so +``` + +These paths represent the current Gluster filesystem layout, which is likely to +be deprecated in favor of the Fedora layout; your paths may vary. At this point + we're ready to configure a volume using our new translator. To do that, I'm +going to suggest something that's strongly discouraged except during +development (the Gluster guys are going to hate me for this): write our own +volfile. Here's just about the simplest volfile you'll ever see. + +``` +volume my-posix + type storage/posix + option directory /srv/export +end-volume + +volume my-rot13 + type encryption/my-rot-13 + subvolumes my-posix +end-volume +``` + +All we have here is a basic brick using `/srv/export` for its data, and then +an instance of our translator layered on top -- no client or server is +necessary for what we're doing, and the system will automatically push a +mount/fuse translator on top if there's no server translator. To try this out, +all we need is the following command (assuming the directories involved already + exist). + +``` +xlator_example$ glusterfs --debug -f my.vol /srv/import +``` + +You should be rewarded with a whole lot of log output, including the text of +the volfile (this is very useful for debugging problems in the field). If you +go to another window on the same machine, you can see that you have a new +filesystem mounted. + +``` +~$ df /srv/import +Filesystem 1K-blocks Used Available Use% Mounted on +/srv/xlator_example/my.vol + 114506240 2706176 105983488 3% /srv/import +``` + +Just for fun, write something into a file in `/srv/import`, then look at the +corresponding file in `/srv/export` to see it all `rot-13`'ed for you. + +``` +~$ echo hello > /srv/import/a_file +~$ cat /srv/export/a_file +uryyb +``` + +There you have it -- functionality you control, implemented easily, layered on +top of local storage. Now you could start adding functionality -- real +encryption, perhaps -- and inevitably having to debug it. You could do that the + old-school way, with `gf_log` (preferred) or even plain old `printf`, or you +could run daemons under `gdb` instead. Alternatively, you could wait for the +next Translator 101 post, where we'll be doing exactly that. + +Debugging a Translator +---------------------- + +Now that we've learned what a translator looks like and how to build one, it's +time to run one and actually watch it work. The best way to do this is good +old-fashioned `gdb`, as follows (using some of the examples from last time). + +``` +xlator_example# gdb glusterfs +GNU gdb (GDB) Red Hat Enterprise Linux (7.2-50.el6) +... +(gdb) r --debug -f my.vol /srv/import +Starting program: /usr/sbin/glusterfs --debug -f my.vol /srv/import +... +[2011-11-23 11:23:16.495516] I [fuse-bridge.c:2971:fuse_init] + 0-glusterfs-fuse: FUSE inited with protocol versions: + glusterfs 7.13 kernel 7.13 +``` + +If you get to this point, your glusterfs client process is already running. You +can go to another window to see the mountpoint, do file operations, etc. + +``` +~# df /srv/import +Filesystem 1K-blocks Used Available Use% Mounted on +/root/xlator_example/my.vol + 114506240 2643968 106045568 3% /srv/import +~# ls /srv/import +a_file +~# cat /srv/import/a_file +hello +``` + +Now let's interrupt the process and see where we are. + +``` + +Program received signal SIGINT, Interrupt. +0x0000003a0060b3dc in pthread_cond_wait@@GLIBC_2.3.2 () + from /lib64/libpthread.so.0 +(gdb) info threads + 5 Thread 0x7fffeffff700 (LWP 27206) 0x0000003a002dd8c7 + in readv () + from /lib64/libc.so.6 + 4 Thread 0x7ffff50e3700 (LWP 27205) 0x0000003a0060b75b + in pthread_cond_timedwait@@GLIBC_2.3.2 () + from /lib64/libpthread.so.0 + 3 Thread 0x7ffff5f02700 (LWP 27204) 0x0000003a0060b3dc + in pthread_cond_wait@@GLIBC_2.3.2 () + from /lib64/libpthread.so.0 + 2 Thread 0x7ffff6903700 (LWP 27203) 0x0000003a0060f245 + in sigwait () + from /lib64/libpthread.so.0 +* 1 Thread 0x7ffff7957700 (LWP 27196) 0x0000003a0060b3dc + in pthread_cond_wait@@GLIBC_2.3.2 () + from /lib64/libpthread.so.0 +``` + +Like any non-toy server, this one has multiple threads. What are they all +doing? Honestly, even I don't know. Thread 1 turns out to be in +`event_dispatch_epoll`, which means it's the one handling all of our network +I/O. Note that with socket multi-threading patch this will change, with one +thread in `socket_poller` per connection. Thread 2 is in `glusterfs_sigwaiter` +which means signals will be isolated to that thread. Thread 3 is in +`syncenv_task`, so it's a worker process for synchronous requests such as +those used by the rebalance and repair code. Thread 4 is in +`janitor_get_next_fd`, so it's waiting for a chance to close no-longer-needed +file descriptors on the local filesystem. (I admit I had to look that one up, +BTW.) Lastly, thread 5 is in `fuse_thread_proc`, so it's the one fetching +requests from our FUSE interface. You'll often see many more threads than +this, but it's a pretty good basic set. Now, let's set a breakpoint so we can +actually watch a request. + +``` +(gdb) b rot13_writev +Breakpoint 1 at 0x7ffff50e4f0b: file rot-13.c, line 119. +(gdb) c +Continuing. +``` + +At this point we go into our other window and do something that will involve a write. + +``` +~# echo goodbye > /srv/import/another_file +(back to the first window) +[Switching to Thread 0x7fffeffff700 (LWP 27206)] + +Breakpoint 1, rot13_writev (frame=0x7ffff6e4402c, this=0x638440, + fd=0x7ffff409802c, vector=0x7fffe8000cd8, count=1, offset=0, + iobref=0x7fffe8001070) at rot-13.c:119 +119 rot_13_private_t *priv = (rot_13_private_t *)this->private; +``` + +Remember how we built with debugging symbols enabled and no optimization? That +will be pretty important for the next few steps. As you can see, we're in +`rot13_writev`, with several parameters. + +* `frame` is our always-present frame pointer for this request. Also, + `frame->local` will point to any local data we created and attached to the + request ourselves. +* `this` is a pointer to our instance of the `rot-13` translator. You can examine + it if you like to see the name, type, options, parent/children, inode table, + and other stuff associated with it. +* `fd` is a pointer to a file-descriptor *object* (`fd_t`, not just a + file-descriptor index which is what most people use "fd" for). This in turn + points to an inode object (`inode_t`) and we can associate our own + `rot-13`-specific data with either of these. +* `vector` and `count` together describe the data buffers for this write, which + we'll get to in a moment. +* `offset` is the offset into the file at which we're writing. +* `iobref` is a buffer-reference object, which is used to track the life cycle + of buffers containing read/write data. If you look closely, you'll notice that + `vector[0].iov_base` points to the same address as `iobref->iobrefs[0].ptr`, which + should give you some idea of the inter-relationships between vector and iobref. + +OK, now what about that `vector`? We can use it to examine the data being +written, like this. + +``` +(gdb) p vector[0] +$2 = {iov_base = 0x7ffff7936000, iov_len = 8} +(gdb) x/s 0x7ffff7936000 +0x7ffff7936000: "goodbye\n" +``` + +It's not always safe to view this data as a string, because it might just as +well be binary data, but since we're generating the write this time it's safe +and convenient. With that knowledge, let's step through things a bit. + +``` +(gdb) s +120 if (priv->encrypt_write) +(gdb) +121 rot13_iovec (vector, count); +(gdb) +rot13_iovec (vector=0x7fffe8000cd8, count=1) at rot-13.c:57 +57 for (i = 0; i < count; i++) { +(gdb) +58 rot13 (vector[i].iov_base, vector[i].iov_len); +(gdb) +rot13 (buf=0x7ffff7936000 "goodbye\n", len=8) at rot-13.c:45 +45 for (i = 0; i < len; i++) { +(gdb) +46 if (buf[i] >= 'a' && buf[i] <= 'z') +(gdb) +47 buf[i] = 'a' + ((buf[i] - 'a' + 13) % 26); +``` + +Here we've stepped into `rot13_iovec`, which iterates through our vector +calling `rot13`, which in turn iterates through the characters in that chunk +doing the `rot-13` operation if/as appropriate. This is pretty straightforward +stuff, so let's skip to the next interesting bit. + +``` +(gdb) fin +Run till exit from #0 rot13 (buf=0x7ffff7936000 "goodbye\n", + len=8) at rot-13.c:47 +rot13_iovec (vector=0x7fffe8000cd8, count=1) at rot-13.c:57 +57 for (i = 0; i < count; i++) { +(gdb) fin +Run till exit from #0 rot13_iovec (vector=0x7fffe8000cd8, + count=1) at rot-13.c:57 +rot13_writev (frame=0x7ffff6e4402c, this=0x638440, + fd=0x7ffff409802c, vector=0x7fffe8000cd8, count=1, + offset=0, iobref=0x7fffe8001070) at rot-13.c:123 +123 STACK_WIND (frame, +(gdb) b 129 +Breakpoint 2 at 0x7ffff50e4f35: file rot-13.c, line 129. +(gdb) b rot13_writev_cbk +Breakpoint 3 at 0x7ffff50e4db3: file rot-13.c, line 106. +(gdb) c +``` + +So we've set breakpoints on both the callback and the statement following the +`STACK_WIND`. Which one will we hit first? + +``` +Breakpoint 3, rot13_writev_cbk (frame=0x7ffff6e4402c, + cookie=0x7ffff6e440d8, this=0x638440, op_ret=8, op_errno=0, + prebuf=0x7fffefffeca0, postbuf=0x7fffefffec30) + at rot-13.c:106 +106 STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, + prebuf, postbuf); +(gdb) bt +#0 rot13_writev_cbk (frame=0x7ffff6e4402c, + cookie=0x7ffff6e440d8, this=0x638440, op_ret=8, op_errno=0, + prebuf=0x7fffefffeca0, postbuf=0x7fffefffec30) + at rot-13.c:106 +#1 0x00007ffff52f1b37 in posix_writev (frame=0x7ffff6e440d8, + this=<value optimized out>, fd=<value optimized out>, + vector=<value optimized out>, count=1, + offset=<value optimized out>, iobref=0x7fffe8001070) + at posix.c:2217 +#2 0x00007ffff50e513e in rot13_writev (frame=0x7ffff6e4402c, + this=0x638440, fd=0x7ffff409802c, vector=0x7fffe8000cd8, + count=1, offset=0, iobref=0x7fffe8001070) at rot-13.c:123 +``` + +Surprise! We're in `rot13_writev_cbk` now, called (indirectly) while we're +still in `rot13_writev` before `STACK_WIND` returns (still at rot-13.c:123). If + you did any request cleanup here, then you need to be careful about what you +do in the remainder of `rot13_writev` because data may have been freed etc. +It's tempting to say you should just do the cleanup in `rot13_writev` after +the `STACK_WIND,` but that's not valid because it's also possible that some +other translator returned without calling `STACK_UNWIND` -- i.e. before +`rot13_writev` is called, so then it would be the one getting null-pointer +errors instead. To put it another way, the callback and the return from +`STACK_WIND` can occur in either order or even simultaneously on different +threads. Even if you were to use reference counts, you'd have to make sure to +use locking or atomic operations to avoid races, and it's not worth it. Unless +you *really* understand the possible flows of control and know what you're +doing, it's better to do cleanup in the callback and nothing after +`STACK_WIND.` + +At this point all that's left is a `STACK_UNWIND` and a return. The +`STACK_UNWIND` invokes our parent's completion callback, and in this case our +parent is FUSE so at that point the VFS layer is notified of the write being +complete. Finally, we return through several levels of normal function calls +until we come back to fuse_thread_proc, which waits for the next request. + +So that's it. For extra fun, you might want to repeat this exercise by stepping +through some other call -- stat or setxattr might be good choices -- but you'll + have to use a translator that actually implements those calls to see much +that's interesting. Then you'll pretty much know everything I knew when I +started writing my first for-real translators, and probably even a bit more. I +hope you've enjoyed this series, or at least found it useful, and if you have +any suggestions for other topics I should cover please let me know (via +comments or email, IRC or Twitter). + +Other versions +-------------- + +Original author's site: + + * [Translator 101 - Setting the Stage](http://pl.atyp.us/hekafs.org/index.php/2011/11/translator-101-class-1-setting-the-stage/) + + * [Translator 101 - Init, Fini and Private Context](http://pl.atyp.us/hekafs.org/index.php/2011/11/translator-101-lesson-2-init-fini-and-private-context/) + + * [Translator 101 - This Time for Real](http://pl.atyp.us/hekafs.org/index.php/2011/11/translator-101-lesson-3-this-time-for-real/) + + * [Translator 101 - Debugging a Translator](http://pl.atyp.us/hekafs.org/index.php/2011/11/translator-101-lesson-4-debugging-a-translator/) + +Gluster community site: + + * [Translators](https://docs.gluster.org/en/latest/Quick-Start-Guide/Architecture/#translators) diff --git a/doc/developer-guide/unittest.md b/doc/developer-guide/unittest.md new file mode 100644 index 00000000000..5c6c0a8a039 --- /dev/null +++ b/doc/developer-guide/unittest.md @@ -0,0 +1,228 @@ +# Unit Tests in GlusterFS + +## Overview +[Art-of-unittesting][definitionofunittest] provides a good definition for unit tests. A good unit test is: + +* Able to be fully automated +* Has full control over all the pieces running (Use mocks or stubs to achieve this isolation when needed) +* Can be run in any order if part of many other tests +* Runs in memory (no DB or File access, for example) +* Consistently returns the same result (You always run the same test, so no random numbers, for example. save those for integration or range tests) +* Runs fast +* Tests a single logical concept in the system +* Readable +* Maintainable +* Trustworthy (when you see its result, you don’t need to debug the code just to be sure) + +## cmocka +GlusterFS unit test framework is based on [cmocka][]. cmocka provides +developers with methods to isolate and test modules written in C language. It +also provides integration with Jenkins by providing JUnit XML compliant unit +test results. + +cmocka + +## Running Unit Tests +To execute the unit tests, all you need is to type `make check`. Here is a step-by-step example assuming you just cloned a GlusterFS tree: + +``` +$ ./autogen.sh +$ ./configure --enable-debug +$ make check +``` + +Sample output: + +``` +PASS: mem_pool_unittest +============================================================================ +Testsuite summary for glusterfs 3git +============================================================================ +# TOTAL: 1 +# PASS: 1 +# SKIP: 0 +# XFAIL: 0 +# FAIL: 0 +# XPASS: 0 +# ERROR: 0 +============================================================================ +``` + +In this example, `mem_pool_unittest` has multiple tests inside, but `make check` assumes that the program itself is the test, and that is why it only shows one test. Here is the output when we run `mem_pool_unittest` directly: + +``` +$ ./libglusterfs/src/mem_pool_unittest +[==========] Running 10 test(s). +[ RUN ] test_gf_mem_acct_enable_set +Expected assertion data != ((void *)0) occurred +[ OK ] test_gf_mem_acct_enable_set +[ RUN ] test_gf_mem_set_acct_info_asserts +Expected assertion xl != ((void *)0) occurred +Expected assertion size > ((4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) + 8) occurred +Expected assertion type <= xl->mem_acct.num_types occurred +[ OK ] test_gf_mem_set_acct_info_asserts +[ RUN ] test_gf_mem_set_acct_info_memory +[ OK ] test_gf_mem_set_acct_info_memory +[ RUN ] test_gf_calloc_default_calloc +[ OK ] test_gf_calloc_default_calloc +[ RUN ] test_gf_calloc_mem_acct_enabled +[ OK ] test_gf_calloc_mem_acct_enabled +[ RUN ] test_gf_malloc_default_malloc +[ OK ] test_gf_malloc_default_malloc +[ RUN ] test_gf_malloc_mem_acct_enabled +[ OK ] test_gf_malloc_mem_acct_enabled +[ RUN ] test_gf_realloc_default_realloc +[ OK ] test_gf_realloc_default_realloc +[ RUN ] test_gf_realloc_mem_acct_enabled +[ OK ] test_gf_realloc_mem_acct_enabled +[ RUN ] test_gf_realloc_ptr +Expected assertion ((void *)0) != ptr occurred +[ OK ] test_gf_realloc_ptr +[==========] 10 test(s) run. +[ PASSED ] 10 test(s). +[ FAILED ] 0 test(s). +[ REPORT ] Created libglusterfs_mem_pool_xunit.xml report +``` + + +## Writing Unit Tests + +### Enhancing your C functions + +#### Programming by Contract +Add the following to your C file: + +```c +#include <cmocka_pbc.h> +``` + +```c +/* + * Programming by Contract is a programming methodology + * which binds the caller and the function called to a + * contract. The contract is represented using Hoare Triple: + * {P} C {Q} + * where {P} is the precondition before executing command C, + * and {Q} is the postcondition. + * + * See also: + * http://en.wikipedia.org/wiki/Design_by_contract + * http://en.wikipedia.org/wiki/Hoare_logic + * http://dlang.org/dbc.html + */ + #ifndef CMOCKERY_PBC_H_ +#define CMOCKERY_PBC_H_ + +#if defined(UNIT_TESTING) || defined (DEBUG) + +#include <assert.h> + +/* + * Checks caller responsibility against contract + */ +#define REQUIRE(cond) assert(cond) + +/* + * Checks function reponsability against contract. + */ +#define ENSURE(cond) assert(cond) + +/* + * While REQUIRE and ENSURE apply to functions, INVARIANT + * applies to classes/structs. It ensures that intances + * of the class/struct are consistent. In other words, + * that the instance has not been corrupted. + */ +#define INVARIANT(invariant_fnc) do{ (invariant_fnc) } while (0); + +#else +#define REQUIRE(cond) do { } while (0); +#define ENSURE(cond) do { } while (0); +#define INVARIANT(invariant_fnc) do{ } while (0); + +#endif /* defined(UNIT_TESTING) || defined (DEBUG) */ +#endif /* CMOCKERY_PBC_H_ */ +``` + +##### Example +This is an _extremely_ simple example: + +```c +int divide (int n, int d) +{ + int ans; + + REQUIRE(d != 0); + + ans = n / d; + + // As code is added to this function throughout its lifetime, + // ENSURE will assert that data will be returned + // according to the contract. Again this is an + // extremely simple example. :-D + ENSURE( ans == (n / d) ); + + return ans; +} + +``` + +##### Important Note +`REQUIRE`, `ENSURE`, and `INVARIANT` are only available when `DEBUG` or `UNIT_TESTING` are set in the CFLAGS. You must pass `--enable-debug` to `./configure` to enable PBC on your non-unittest builds. + +#### Overriding functions +Cmockery2 provides its own memory allocation functions which check for buffer overrun and memory leaks. The following header file must be included **last** to be able to override any of the memory allocation functions: + +```c +#include <cmocka.h> +``` + +This file will only take effect with the `UNIT_TESTING` CFLAG is set. + +### Creating a unit test +Once you identify the C file you would like to test, first create a `unittest` directory under the directory where the C file is located. This will isolate the unittests to a different directory. + +Next, you need to edit the `Makefile.am` file in the directory where your C file is located. Initialize the +`Makefile.am` if it does not already have the following sections: + +``` +#### UNIT TESTS ##### +CLEANFILES += *.gcda *.gcno *_xunit.xml +noinst_PROGRAMS = +TESTS = +``` + +Now you can add the following for each of the unit tests that you would like to build: + +``` +### UNIT TEST xxx_unittest ### +xxx_unittest_CPPFLAGS = $(xxx_CPPFLAGS) +xxx_unittest_SOURCES = xxx.c \ + unittest/xxx_unittest.c +xxx_unittest_CFLAGS = $(UNITTEST_CFLAGS) +xxx_unittest_LDFLAGS = $(UNITTEST_LDFLAGS) +noinst_PROGRAMS += xxx_unittest +TESTS += xxx_unittest +``` + +Where `xxx` is the name of your C file. For example, look at `libglusterfs/src/Makefile.am`. + +Copy the simple unit test from the [cmocka API][cmockaapi] to `unittest/xxx_unittest.c`. If you would like to see an example of a unit test, please refer to `libglusterfs/src/unittest/mem_pool_unittest.c`. + +#### Mocking +You may see that the linker will complain about missing functions needed by the C file you would like to test. Identify the required functions, then place their stubs in a file called `unittest/xxx_mock.c`, then include this file in `Makefile.am` in `xxx_unittest_SOURCES`. This will allow you to you Cmockery2's mocking functions. + +#### Running the unit test +You can type `make` in the directory where the C file is located. Once you built it and there are no errors, you can execute the test either by directly executing the program (in our example above it is called `xxx_unittest` ), or by running `make check`. + +#### Debugging +Sometimes you may need to debug your unit test. To do that, you will have to point `gdb` to the binary which is located in the same directory as the source. For example, you can do the following from the root of the source tree to debug `mem_pool_unittest`: + +``` +$ gdb libglusterfs/src/mem_pool_unittest +``` + + +[cmocka]: https://cmocka.org +[definitionofunittest]: http://artofunittesting.com/definition-of-a-unit-test/ +[cmockapi]: https://api.cmocka.org diff --git a/doc/developer-guide/versioning.md b/doc/developer-guide/versioning.md new file mode 100644 index 00000000000..10c1511b79b --- /dev/null +++ b/doc/developer-guide/versioning.md @@ -0,0 +1,44 @@ +Versioning +========== + +### current + +The number of the current interface exported by the library. A current value +of '1', means that you are calling the interface exported by this library +interface 1. + +### revision + +The implementation number of the most recent interface exported by this library. +In this case, a revision value of `0` means that this is the first +implementation of the interface. + +If the next release of this library exports the same interface, but has a +different implementation (perhaps some bugs have been fixed), the revision +number will be higher, but current number will be the same. In that case, when +given a choice, the library with the highest revision will always be used by +the runtime loader. + +### age + +The number of previous additional interfaces supported by this library. If age +were '2', then this library can be linked into executables which were built with +a release of this library that exported the current interface number, current, +or any of the previous two interfaces. By definition age must be less than or +equal to current. At the outset, only the first ever interface is implemented, +so age can only be `0'. + +For every release of the library `-version-info` argument needs to be set +correctly depending on any interface changes you have made. + +This is quite straightforward when you understand what the three numbers mean: + +If you have changed any of the sources for this library, the revision number +must be incremented. This is a new revision of the current interface. If the +interface has changed, then current must be incremented, and revision reset +to '0'. + +This is the first revision of a new interface. If the new interface is a +superset of the previous interface (that is, if the previous interface has not +been broken by the changes in this new release), then age must be incremented. +This release is backwards compatible with the previous release. diff --git a/doc/developer-guide/write-behind.md b/doc/developer-guide/write-behind.md new file mode 100644 index 00000000000..0d78964fa20 --- /dev/null +++ b/doc/developer-guide/write-behind.md @@ -0,0 +1,56 @@ +performance/write-behind translator +=================================== + +Basic working +-------------- + +Write behind is basically a translator to lie to the application that the +write-requests are finished, even before it is actually finished. + +On a regular translator tree without write-behind, control flow is like this: + +1. application makes a `write()` system call. +2. VFS ==> FUSE ==> `/dev/fuse`. +3. fuse-bridge initiates a glusterfs `writev()` call. +4. `writev()` is `STACK_WIND()`ed up to client-protocol or storage translator. +5. client-protocol, on receiving reply from server, starts `STACK_UNWIND()` towards the fuse-bridge. + +On a translator tree with write-behind, control flow is like this: + +1. application makes a `write()` system call. +2. VFS ==> FUSE ==> `/dev/fuse`. +3. fuse-bridge initiates a glusterfs `writev()` call. +4. `writev()` is `STACK_WIND()`ed up to write-behind translator. +5. write-behind adds the write buffer to its internal queue and does a `STACK_UNWIND()` towards the fuse-bridge. + +write call is completed in application's percepective. after +`STACK_UNWIND()`ing towards the fuse-bridge, write-behind initiates a fresh +writev() call to its child translator, whose replies will be consumed by +write-behind itself. Write-behind _doesn't_ cache the write buffer, unless +`option flush-behind on` is specified in volume specification file. + +Windowing +--------- + +With respect to write-behind, each write-buffer has three flags: `stack_wound`, `write_behind` and `got_reply`. + +* `stack_wound`: if set, indicates that write-behind has initiated `STACK_WIND()` towards child translator. +* `write_behind`: if set, indicates that write-behind has done `STACK_UNWIND()` towards fuse-bridge. +* `got_reply`: if set, indicates that write-behind has received reply from child translator for a `writev()` `STACK_WIND()`. a request will be destroyed by write-behind only if this flag is set. + +Currently pending write requests = aggregate size of requests with write_behind = 1 and got_reply = 0. + +window size limits the aggregate size of currently pending write requests. once +the pending requests' size has reached the window size, write-behind blocks +writev() calls from fuse-bridge. Blocking is only from application's +perspective. Write-behind does `STACK_WIND()` to child translator +straight-away, but hold behind the `STACK_UNWIND()` towards fuse-bridge. +`STACK_UNWIND()` is done only once write-behind gets enough replies to +accommodate for currently blocked request. + +Flush behind +------------ + +If `option flush-behind on` is specified in volume specification file, then +write-behind sends aggregate write requests to child translator, instead of +regular per request `STACK_WIND()`s. diff --git a/doc/developer-guide/writing-a-cloudsync-plugin.md b/doc/developer-guide/writing-a-cloudsync-plugin.md new file mode 100644 index 00000000000..907860aaed8 --- /dev/null +++ b/doc/developer-guide/writing-a-cloudsync-plugin.md @@ -0,0 +1,164 @@ +## How to write your Cloudsync Plugin + +### Background + +Cloudsync translator is part of the archival feature in Gluster. This translator +does the retrieval/download part. Each cold file will be archived to a remote +storage (public or private cloud). On future access to the file, it will be +retrieved from the remote storage by Cloudsync translator. Each remote storage +would need a unique plugin. Cloudsync translator will load this plugin and +call the necessary plugin functions. + +Upload can be done by a script or program. There are some basic mandatory steps +for uploading the data. There is a sample script for crawl and upload given at +the end of this guide. + +### Necessary changes to create a plugin + +1. Define store_methods: + +* This structure is the container of basic functions that will be called by + cloudsync xlator. + + typedef struct store_methodds { + int (*fop_download) (call_frame_t *frame, void *config); + /* return type should be the store config */ + void *(*fop_init) (xlator_t *this); + int (*fop_reconfigure) (xlator_t *this, dict_t *options); + void (*fop_fini) (void *config); + } store_methods_t; + + + Member details: + fop_download: + This is the download function pointer. + + frame: This will have the fd to write data downloaded from + cloud to GlusterFS.(frame->local->fd) + + config: This is the plugin configuration variable. + + Note: Structure cs_local_t has member dlfd and dloffset which + can be used to manage the writes to Glusterfs. + Include cloudsync-common.h to access these structures. + + fop_init: + This is similar to xlator init. But here the return value is + the plugin configuration pointer. This pointer will be stored + in the cloudsync private object (priv->stores->config). And + the cloudsync private object can be accessed by "this->private" + where "this" is of type xlator_t. + + fop_reconfigure: + This is similar to xlator_reconfigure. + + fop_fini: + Free plugin resources. + + Note: Store_methods_t is part of cs_private_t which in turn part of + xlator_t. Create a store_methods_t object named "store_ops" in + your plugin. For example + + store_methods_t store_ops = { + .fop_download = aws_download_s3, + .fop_init = aws_init, + .fop_reconfigure = aws_reconfigure, + .fop_fini = aws_fini, + }; + + +2 - Making Cloudsync xlator aware of the plugin: + + Add an entry in to the cs_plugin structure. For example + struct cs_plugin plugins[] = { + { + .name = "amazons3", + .library = "libamazons3.so", + .description = "amazon s3 store." + }, + + {.name = NULL}, + }; + + Description about individual members: + name: name of the plugin + library: This is the shared object created. Cloudsync will load + this library during init. + description: Describe about the plugin. + +3- Makefile Changes in Cloudsync: + + Add <plugin.la> to cloudsync_la_LIBADD variable. + +4 - Configure.ac changes: + + In cloudsync section add the necessary dependency checks for + the plugin. + +5 - Export symbols: + + Cloudsync needs "store_ops" to resolve all plugin functions. + Create a file <plugin>.sym and add write "store_ops" to it. + + +### Sample script for upload +This script assumes amazon s3 is the target cloud and bucket name is +gluster-bucket. User can do necessary aws configuration using command +"aws configure". Currently for amazons3 there are four gluster settings +available. +1- features.s3plugin-seckey -> s3 secret key +2- features.s3plugin-keyid -> s3 key id +3- features.s3plugin-bucketid -> bucketid +4- features.s3plugin-hostname -> hostname e.g. s3.amazonaws.com + +Additionally set cloudsync storetype to amazons3. + +gluster v set <VOLNAME> cloudsync-storetype amazons3 + +Now create a mount dedicated for this upload task. + +That covers necessary configurations needed. + +Below is the sample script for upload. The script will crawl directly on the +brick and will upload those files which are not modified for last one month. +It needs two arguments. +1st arguement - Gluster Brick path +2nd arguement - coldness that is how many days since the file was modified. +3rd argument - dedicated gluster mount point created for uploading. + +Once the cloud setup is done, run the following script on individual bricks. +Note: For an AFR volume, pick only the fully synchronized brick among the +replica bricks. + +``` +target_folder=$1 +coldness=$2 +mnt=$3 + +cd $target_folder +for i in `find . -type f | grep -v "glusterfs" | sed 's/..//'` +do + echo "processing $mnt/$i" + + #check whether the file is already archived + getfattr -n trusted.glusterfs.cs.remote $i &> /dev/null + if [ $? -eq 0 ] + then + echo "file $mnt/$i is already archived" + else + #upload to cloud + aws s3 cp $mnt/$i s3://gluster-bucket/ + mtime=`stat -c "%Y" $mnt/$i` + + #post processing of upload + setfattr -n trusted.glusterfs.csou.complete -v $mtime $mnt/$i + if [ $? -ne 0 ] + then + echo "archiving of file $mnt/$i failed" + else + echo "archiving of file $mnt/$i succeeded" + fi + + fi +done +``` diff --git a/doc/developer-guide/xlator-classification.md b/doc/developer-guide/xlator-classification.md new file mode 100644 index 00000000000..6073df9375f --- /dev/null +++ b/doc/developer-guide/xlator-classification.md @@ -0,0 +1,221 @@ +# xlator categories and expectations + +The purpose of the document is to define a category for various xlators +and expectations around what each category means from a perspective of +health and maintenance of a xlator. + +The need to do this is to ensure certain categories are kept in good +health, and helps the community and contributors focus their efforts around the +same. + +This document also provides implementation details for xlator developers to +declare a category for any xlator. + +## Table of contents +1. Audience +2. Categories (and expectations of each category) +3. Implementation and usage details + +## Audience + +This document is intended for the following community participants, +- New xlator contributors +- Existing xlator maintainers +- Packaging and gluster management stack maintainers + +For a more user facing understanding it is recommended to read section (TBD) +in the gluster documentation. + +## Categories +1. Experimental (E) +2. TechPreview (TP) +3. Maintained (M) +4. Deprecated (D) +5. Obsolete (O) + +### Experimental (E) + +Developed in the experimental branch, for exploring new features. These xlators +are NEVER packaged as a part of releases, interested users and contributors can +build and work with these from sources. In the future, these maybe available as +an package based on a weekly build of the same. + +#### Quality expectations +- Compiles or passes smoke tests +- Does not break nightly experimental regressions + - NOTE: If a nightly is broken, then all patches that were merged are reverted + till the errant patch is found and subsequently fixed + +### TechPreview (TP) + +Xlators in master or release branches that are not deemed fit to be in +production deployments, but are feature complete to invite feedback and host +user data. + +These xlators will be worked upon with priority by maintainers/authors who are +involved in making them more stable than xlators in the Experimental/Deprecated/ +Obsolete categories. + +There is no guarantee that these xlators will move to the Maintained state, and +may just get Obsoleted based on feedback, or other project goals or technical +alternatives. + +#### Quality expectations +- Same as Maintained, minus + - Performance, Scale, other(?) + - *TBD* *NOTE* Need inputs, Intention is all quality goals as in Maintained, + other than the list above (which for now has scale and performance) + +### Maintained (M) + +These xltors are part of the core Gluster functionality and are maintained +actively. These are part of master and release branches and are higher in +priority of maintainers and other interested contributors. + +#### Quality expectations + +NOTE: A short note on what each of these mean are added here, details to follow. + +NOTE: Out of the gate all of the following are not mandated, consider the +following a desirable state to reach as we progress on each + +- Bug backlog: Actively address bug backlog +- Enhancement backlog: Actively maintain outstanding enhancement backlog (need + not be acted on, but should be visible to all) +- Review backlog: Actively keep this below desired counts and states +- Static code health: Actively meet near-zero issues in this regard + - Coverity, spellcheck and other checks +- Runtime code health: Actively meet defined coverage levels in this regard + - Coverage, others? + - Per-patch regressions + - Glusto runs + - Performance + - Scalability +- Technical specifications: Implementation details should be documented and + updated at regular cadence (even per patch that change assumptions in + here) +- User documentation: User facing details should be maintained to current + status in the documentation +- Debuggability: Steps, tools, procedures should be documented and maintained + each release/patch as applicable +- Troubleshooting: Steps, tools, procedures should be documented and maintained + each release/patch as applicable + - Steps/guides for self service + - Knowledge base for problems +- Other common criteria that will apply: Required metrics/desired states to be + defined per criteria + - Monitoring, usability, statedump, and other such xlator expectations + +### Deprecated (D) + +Xlators on master or release branches that would be obsoleted and/or replaced +with similar or other functionality in the next major release. + +#### Quality expectations +- Retain status-quo when moved to this state, till it is moved to obsoleted +- Provide migration steps if feature provided by the xlator is replaced with +other xlators + +### Obsolete (O) + +Xlator/code still in tree, but not packaged or shipped or maintained in any +form. This is noted as a category till the code is removed from the tree. + +These xlators and their corresponding code and test health will not be executed. + +#### Quality expectations +- None + +## Implementation and usage details + +### How to specify an xlators category + +While defining 'xlator_api_t' structure for the corresponding xlator, add a +flag like below: + +``` +diff --git a/xlators/performance/nl-cache/src/nl-cache.c b/xlators/performance/nl-cache/src/nl-cache.c +index 0f0e53bac2..8267d6897c 100644 +--- a/xlators/performance/nl-cache/src/nl-cache.c ++++ b/xlators/performance/nl-cache/src/nl-cache.c +@@ -869,4 +869,5 @@ xlator_api_t xlator_api = { + .cbks = &nlc_cbks, + .options = nlc_options, + .identifier = "nl-cache", ++ .category = GF_TECH_PREVIEW, + }; +diff --git a/xlators/performance/quick-read/src/quick-read.c b/xlators/performance/quick-read/src/quick-read.c +index 8d39720e7f..235de27c19 100644 +--- a/xlators/performance/quick-read/src/quick-read.c ++++ b/xlators/performance/quick-read/src/quick-read.c +@@ -1702,4 +1702,5 @@ xlator_api_t xlator_api = { + .cbks = &qr_cbks, + .options = qr_options, + .identifier = "quick-read", ++ .category = GF_MAINTAINED, + }; +``` + +Similarly, if a particular option is in different state other than +the xlator state, one can add the same flag in options structure too. + +``` +diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c +index 0e86e33d03..81996743d1 100644 +--- a/xlators/cluster/afr/src/afr.c ++++ b/xlators/cluster/afr/src/afr.c +@@ -772,6 +772,7 @@ struct volume_options options[] = { + .description = "Maximum latency for shd halo replication in msec." + }, + { .key = {"halo-enabled"}, ++ .category = GF_TECH_PREVIEW, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "False", + +``` + + +### User experience using the categories + +#### Ability to use a category + +This section details which category of xlators can be used when and specifics +around when each category is enabled. + +1. Maintained category xlators can be used by default, this implies, volumes +created with these xlators enabled will throw no warnings, or need no user +intervention to use the xlator. + +2. Tech Preview category xlators needs cluster configuration changes to allow +these xlatorss to be used in volumes, further, logs will contain a message +stating TP xlators are in use. Without the cluster configured to allow TP +xlators, volumes created or edited to use such xlators would result in errors. + - (TBD) Cluster configuration option + - (TBD) Warning message + - (TBD) Code mechanics on how this is achieved + +3. Deprecated category xlators can be used by default, but will throw a warning +in the logs that such are in use and will be deprecated in the future. + - (TBD) Warning message + +4. Obsolete category xlators will not be packaged and hence cannot be used from +release builds. + +5. Experimental category xlators will not be packaged and hence cannot be used +from release builds, if running experimental (weekly or other such) builds, +these will throw a warning in the logs stating experimental xlators are in use. + - (TBD) Warning message + +#### Ability to query xlator category + +(TBD) Need to provide the ability to query xlator categories, or list xlators +and their respective categories. + +#### User facing changes + +User facing changes that are expected due to this change include the following, +- Cluster wide option to enable TP xlators, or more generically a category +level of xlators +- Errors in commands that fail due to invalid categories +- Warning messages in logs to denote certain categories of xlators are in use +- (TBD) Ability to query xlators and their respective categories diff --git a/doc/errno.list.bsd.txt b/doc/errno.list.bsd.txt deleted file mode 100644 index 350af25e4ab..00000000000 --- a/doc/errno.list.bsd.txt +++ /dev/null @@ -1,376 +0,0 @@ -/*- - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)errno.h 8.5 (Berkeley) 1/21/94 - * $FreeBSD: src/sys/sys/errno.h,v 1.28 2005/04/02 12:33:28 das Exp $ - */ - -#ifndef _SYS_ERRNO_H_ -#define _SYS_ERRNO_H_ - -#ifndef _KERNEL -#include <sys/cdefs.h> -__BEGIN_DECLS -int * __error(void); -__END_DECLS -#define errno (* __error()) -#endif - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* Input/output error */ -#define ENXIO 6 /* Device not configured */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file descriptor */ -#define ECHILD 10 /* No child processes */ -#define EDEADLK 11 /* Resource deadlock avoided */ - /* 11 was EAGAIN */ -#define ENOMEM 12 /* Cannot allocate memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#ifndef _POSIX_SOURCE -#define ENOTBLK 15 /* Block device required */ -#endif -#define EBUSY 16 /* Device busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* Operation not supported by device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* Too many open files in system */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Inappropriate ioctl for device */ -#ifndef _POSIX_SOURCE -#define ETXTBSY 26 /* Text file busy */ -#endif -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only filesystem */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ - -/* math software */ -#define EDOM 33 /* Numerical argument out of domain */ -#define ERANGE 34 /* Result too large */ - -/* non-blocking and interrupt i/o */ -#define EAGAIN 35 /* Resource temporarily unavailable */ -#ifndef _POSIX_SOURCE -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define EINPROGRESS 36 /* Operation now in progress */ -#define EALREADY 37 /* Operation already in progress */ - -/* ipc/network software -- argument errors */ -#define ENOTSOCK 38 /* Socket operation on non-socket */ -#define EDESTADDRREQ 39 /* Destination address required */ -#define EMSGSIZE 40 /* Message too long */ -#define EPROTOTYPE 41 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 42 /* Protocol not available */ -#define EPROTONOSUPPORT 43 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ -#define EOPNOTSUPP 45 /* Operation not supported */ -#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -#define EPFNOSUPPORT 46 /* Protocol family not supported */ -#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ -#define EADDRINUSE 48 /* Address already in use */ -#define EADDRNOTAVAIL 49 /* Can't assign requested address */ - -/* ipc/network software -- operational errors */ -#define ENETDOWN 50 /* Network is down */ -#define ENETUNREACH 51 /* Network is unreachable */ -#define ENETRESET 52 /* Network dropped connection on reset */ -#define ECONNABORTED 53 /* Software caused connection abort */ -#define ECONNRESET 54 /* Connection reset by peer */ -#define ENOBUFS 55 /* No buffer space available */ -#define EISCONN 56 /* Socket is already connected */ -#define ENOTCONN 57 /* Socket is not connected */ -#define ESHUTDOWN 58 /* Can't send after socket shutdown */ -#define ETOOMANYREFS 59 /* Too many references: can't splice */ -#define ETIMEDOUT 60 /* Operation timed out */ -#define ECONNREFUSED 61 /* Connection refused */ - -#define ELOOP 62 /* Too many levels of symbolic links */ -#endif /* _POSIX_SOURCE */ -#define ENAMETOOLONG 63 /* File name too long */ - -/* should be rearranged */ -#ifndef _POSIX_SOURCE -#define EHOSTDOWN 64 /* Host is down */ -#define EHOSTUNREACH 65 /* No route to host */ -#endif /* _POSIX_SOURCE */ -#define ENOTEMPTY 66 /* Directory not empty */ - -/* quotas & mush */ -#ifndef _POSIX_SOURCE -#define EPROCLIM 67 /* Too many processes */ -#define EUSERS 68 /* Too many users */ -#define EDQUOT 69 /* Disc quota exceeded */ - -/* Network File System */ -#define ESTALE 70 /* Stale NFS file handle */ -#define EREMOTE 71 /* Too many levels of remote in path */ -#define EBADRPC 72 /* RPC struct is bad */ -#define ERPCMISMATCH 73 /* RPC version wrong */ -#define EPROGUNAVAIL 74 /* RPC prog. not avail */ -#define EPROGMISMATCH 75 /* Program version wrong */ -#define EPROCUNAVAIL 76 /* Bad procedure for program */ -#endif /* _POSIX_SOURCE */ - -#define ENOLCK 77 /* No locks available */ -#define ENOSYS 78 /* Function not implemented */ - -#ifndef _POSIX_SOURCE -#define EFTYPE 79 /* Inappropriate file type or format */ -#define EAUTH 80 /* Authentication error */ -#define ENEEDAUTH 81 /* Need authenticator */ -#define EIDRM 82 /* Identifier removed */ -#define ENOMSG 83 /* No message of desired type */ -#define EOVERFLOW 84 /* Value too large to be stored in data type */ -#define ECANCELED 85 /* Operation canceled */ -#define EILSEQ 86 /* Illegal byte sequence */ -#define ENOATTR 87 /* Attribute not found */ - -#define EDOOFUS 88 /* Programming error */ -#endif /* _POSIX_SOURCE */ - -#define EBADMSG 89 /* Bad message */ -#define EMULTIHOP 90 /* Multihop attempted */ -#define ENOLINK 91 /* Link has been severed */ -#define EPROTO 92 /* Protocol error */ - -#ifndef _POSIX_SOURCE -#define ELAST 92 /* Must be equal largest errno */ -#endif /* _POSIX_SOURCE */ - -#ifdef _KERNEL -/* pseudo-errors returned inside kernel to modify return to process */ -#define ERESTART (-1) /* restart syscall */ -#define EJUSTRETURN (-2) /* don't modify regs, just return */ -#define ENOIOCTL (-3) /* ioctl not handled by this layer */ -#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */ -#endif - -#endif -/*- - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)errno.h 8.5 (Berkeley) 1/21/94 - * $FreeBSD: src/sys/sys/errno.h,v 1.28 2005/04/02 12:33:28 das Exp $ - */ - -#ifndef _SYS_ERRNO_H_ -#define _SYS_ERRNO_H_ - -#ifndef _KERNEL -#include <sys/cdefs.h> -__BEGIN_DECLS -int * __error(void); -__END_DECLS -#define errno (* __error()) -#endif - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* Input/output error */ -#define ENXIO 6 /* Device not configured */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file descriptor */ -#define ECHILD 10 /* No child processes */ -#define EDEADLK 11 /* Resource deadlock avoided */ - /* 11 was EAGAIN */ -#define ENOMEM 12 /* Cannot allocate memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#ifndef _POSIX_SOURCE -#define ENOTBLK 15 /* Block device required */ -#endif -#define EBUSY 16 /* Device busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* Operation not supported by device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* Too many open files in system */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Inappropriate ioctl for device */ -#ifndef _POSIX_SOURCE -#define ETXTBSY 26 /* Text file busy */ -#endif -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only filesystem */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ - -/* math software */ -#define EDOM 33 /* Numerical argument out of domain */ -#define ERANGE 34 /* Result too large */ - -/* non-blocking and interrupt i/o */ -#define EAGAIN 35 /* Resource temporarily unavailable */ -#ifndef _POSIX_SOURCE -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define EINPROGRESS 36 /* Operation now in progress */ -#define EALREADY 37 /* Operation already in progress */ - -/* ipc/network software -- argument errors */ -#define ENOTSOCK 38 /* Socket operation on non-socket */ -#define EDESTADDRREQ 39 /* Destination address required */ -#define EMSGSIZE 40 /* Message too long */ -#define EPROTOTYPE 41 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 42 /* Protocol not available */ -#define EPROTONOSUPPORT 43 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ -#define EOPNOTSUPP 45 /* Operation not supported */ -#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -#define EPFNOSUPPORT 46 /* Protocol family not supported */ -#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ -#define EADDRINUSE 48 /* Address already in use */ -#define EADDRNOTAVAIL 49 /* Can't assign requested address */ - -/* ipc/network software -- operational errors */ -#define ENETDOWN 50 /* Network is down */ -#define ENETUNREACH 51 /* Network is unreachable */ -#define ENETRESET 52 /* Network dropped connection on reset */ -#define ECONNABORTED 53 /* Software caused connection abort */ -#define ECONNRESET 54 /* Connection reset by peer */ -#define ENOBUFS 55 /* No buffer space available */ -#define EISCONN 56 /* Socket is already connected */ -#define ENOTCONN 57 /* Socket is not connected */ -#define ESHUTDOWN 58 /* Can't send after socket shutdown */ -#define ETOOMANYREFS 59 /* Too many references: can't splice */ -#define ETIMEDOUT 60 /* Operation timed out */ -#define ECONNREFUSED 61 /* Connection refused */ - -#define ELOOP 62 /* Too many levels of symbolic links */ -#endif /* _POSIX_SOURCE */ -#define ENAMETOOLONG 63 /* File name too long */ - -/* should be rearranged */ -#ifndef _POSIX_SOURCE -#define EHOSTDOWN 64 /* Host is down */ -#define EHOSTUNREACH 65 /* No route to host */ -#endif /* _POSIX_SOURCE */ -#define ENOTEMPTY 66 /* Directory not empty */ - -/* quotas & mush */ -#ifndef _POSIX_SOURCE -#define EPROCLIM 67 /* Too many processes */ -#define EUSERS 68 /* Too many users */ -#define EDQUOT 69 /* Disc quota exceeded */ - -/* Network File System */ -#define ESTALE 70 /* Stale NFS file handle */ -#define EREMOTE 71 /* Too many levels of remote in path */ -#define EBADRPC 72 /* RPC struct is bad */ -#define ERPCMISMATCH 73 /* RPC version wrong */ -#define EPROGUNAVAIL 74 /* RPC prog. not avail */ -#define EPROGMISMATCH 75 /* Program version wrong */ -#define EPROCUNAVAIL 76 /* Bad procedure for program */ -#endif /* _POSIX_SOURCE */ - -#define ENOLCK 77 /* No locks available */ -#define ENOSYS 78 /* Function not implemented */ - -#ifndef _POSIX_SOURCE -#define EFTYPE 79 /* Inappropriate file type or format */ -#define EAUTH 80 /* Authentication error */ -#define ENEEDAUTH 81 /* Need authenticator */ -#define EIDRM 82 /* Identifier removed */ -#define ENOMSG 83 /* No message of desired type */ -#define EOVERFLOW 84 /* Value too large to be stored in data type */ -#define ECANCELED 85 /* Operation canceled */ -#define EILSEQ 86 /* Illegal byte sequence */ -#define ENOATTR 87 /* Attribute not found */ - -#define EDOOFUS 88 /* Programming error */ -#endif /* _POSIX_SOURCE */ - -#define EBADMSG 89 /* Bad message */ -#define EMULTIHOP 90 /* Multihop attempted */ -#define ENOLINK 91 /* Link has been severed */ -#define EPROTO 92 /* Protocol error */ - -#ifndef _POSIX_SOURCE -#define ELAST 92 /* Must be equal largest errno */ -#endif /* _POSIX_SOURCE */ - -#ifdef _KERNEL -/* pseudo-errors returned inside kernel to modify return to process */ -#define ERESTART (-1) /* restart syscall */ -#define EJUSTRETURN (-2) /* don't modify regs, just return */ -#define ENOIOCTL (-3) /* ioctl not handled by this layer */ -#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */ -#endif - -#endif diff --git a/doc/errno.list.linux.txt b/doc/errno.list.linux.txt deleted file mode 100644 index baa50792d4d..00000000000 --- a/doc/errno.list.linux.txt +++ /dev/null @@ -1,1586 +0,0 @@ -#define ICONV_SUPPORTS_ERRNO 1 -#include <errno.h> -/* Error constants. Linux specific version. - Copyright (C) 1996, 1997, 1998, 1999, 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifdef _ERRNO_H - -# undef EDOM -# undef EILSEQ -# undef ERANGE -# include <linux/errno.h> - -/* Linux has no ENOTSUP error code. */ -# define ENOTSUP EOPNOTSUPP - -/* Older Linux versions also had no ECANCELED error code. */ -# ifndef ECANCELED -# define ECANCELED 125 -# endif - -/* Support for error codes to support robust mutexes was added later, too. */ -# ifndef EOWNERDEAD -# define EOWNERDEAD 130 -# define ENOTRECOVERABLE 131 -# endif - -# ifndef __ASSEMBLER__ -/* Function to get address of global `errno' variable. */ -extern int *__errno_location (void) __THROW __attribute__ ((__const__)); - -# if !defined _LIBC || defined _LIBC_REENTRANT -/* When using threads, errno is a per-thread value. */ -# define errno (*__errno_location ()) -# endif -# endif /* !__ASSEMBLER__ */ -#endif /* _ERRNO_H */ - -#if !defined _ERRNO_H && defined __need_Emath -/* This is ugly but the kernel header is not clean enough. We must - define only the values EDOM, EILSEQ and ERANGE in case __need_Emath is - defined. */ -# define EDOM 33 /* Math argument out of domain of function. */ -# define EILSEQ 84 /* Illegal byte sequence. */ -# define ERANGE 34 /* Math result not representable. */ -#endif /* !_ERRNO_H && __need_Emath */ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef APR_ERRNO_H -#define APR_ERRNO_H - -/** - * @file apr_errno.h - * @brief APR Error Codes - */ - -#include "apr.h" - -#if APR_HAVE_ERRNO_H -#include <errno.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup apr_errno Error Codes - * @ingroup APR - * @{ - */ - -/** - * Type for specifying an error or status code. - */ -typedef int apr_status_t; - -/** - * Return a human readable string describing the specified error. - * @param statcode The error code the get a string for. - * @param buf A buffer to hold the error string. - * @param bufsize Size of the buffer to hold the string. - */ -APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, - apr_size_t bufsize); - -#if defined(DOXYGEN) -/** - * @def APR_FROM_OS_ERROR(os_err_type syserr) - * Fold a platform specific error into an apr_status_t code. - * @return apr_status_t - * @param e The platform os error code. - * @warning macro implementation; the syserr argument may be evaluated - * multiple times. - */ -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) - -/** - * @def APR_TO_OS_ERROR(apr_status_t statcode) - * @return os_err_type - * Fold an apr_status_t code back to the native platform defined error. - * @param e The apr_status_t folded platform os error code. - * @warning macro implementation; the statcode argument may be evaluated - * multiple times. If the statcode was not created by apr_get_os_error - * or APR_FROM_OS_ERROR, the results are undefined. - */ -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -/** @def apr_get_os_error() - * @return apr_status_t the last platform error, folded into apr_status_t, on most platforms - * @remark This retrieves errno, or calls a GetLastError() style function, and - * folds it with APR_FROM_OS_ERROR. Some platforms (such as OS2) have no - * such mechanism, so this call may be unsupported. Do NOT use this - * call for socket errors from socket, send, recv etc! - */ - -/** @def apr_set_os_error(e) - * Reset the last platform error, unfolded from an apr_status_t, on some platforms - * @param e The OS error folded in a prior call to APR_FROM_OS_ERROR() - * @warning This is a macro implementation; the statcode argument may be evaluated - * multiple times. If the statcode was not created by apr_get_os_error - * or APR_FROM_OS_ERROR, the results are undefined. This macro sets - * errno, or calls a SetLastError() style function, unfolding statcode - * with APR_TO_OS_ERROR. Some platforms (such as OS2) have no such - * mechanism, so this call may be unsupported. - */ - -/** @def apr_get_netos_error() - * Return the last socket error, folded into apr_status_t, on all platforms - * @remark This retrieves errno or calls a GetLastSocketError() style function, - * and folds it with APR_FROM_OS_ERROR. - */ - -/** @def apr_set_netos_error(e) - * Reset the last socket error, unfolded from an apr_status_t - * @param e The socket error folded in a prior call to APR_FROM_OS_ERROR() - * @warning This is a macro implementation; the statcode argument may be evaluated - * multiple times. If the statcode was not created by apr_get_os_error - * or APR_FROM_OS_ERROR, the results are undefined. This macro sets - * errno, or calls a WSASetLastError() style function, unfolding - * socketcode with APR_TO_OS_ERROR. - */ - -#endif /* defined(DOXYGEN) */ - -/** - * APR_OS_START_ERROR is where the APR specific error values start. - */ -#define APR_OS_START_ERROR 20000 -/** - * APR_OS_ERRSPACE_SIZE is the maximum number of errors you can fit - * into one of the error/status ranges below -- except for - * APR_OS_START_USERERR, which see. - */ -#define APR_OS_ERRSPACE_SIZE 50000 -/** - * APR_OS_START_STATUS is where the APR specific status codes start. - */ -#define APR_OS_START_STATUS (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE) -/** - * APR_OS_START_USERERR are reserved for applications that use APR that - * layer their own error codes along with APR's. Note that the - * error immediately following this one is set ten times farther - * away than usual, so that users of apr have a lot of room in - * which to declare custom error codes. - */ -#define APR_OS_START_USERERR (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE) -/** - * APR_OS_START_USEERR is obsolete, defined for compatibility only. - * Use APR_OS_START_USERERR instead. - */ -#define APR_OS_START_USEERR APR_OS_START_USERERR -/** - * APR_OS_START_CANONERR is where APR versions of errno values are defined - * on systems which don't have the corresponding errno. - */ -#define APR_OS_START_CANONERR (APR_OS_START_USERERR \ - + (APR_OS_ERRSPACE_SIZE * 10)) -/** - * APR_OS_START_EAIERR folds EAI_ error codes from getaddrinfo() into - * apr_status_t values. - */ -#define APR_OS_START_EAIERR (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE) -/** - * APR_OS_START_SYSERR folds platform-specific system error values into - * apr_status_t values. - */ -#define APR_OS_START_SYSERR (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE) - -/** no error. */ -#define APR_SUCCESS 0 - -/** - * @defgroup APR_Error APR Error Values - * <PRE> - * <b>APR ERROR VALUES</b> - * APR_ENOSTAT APR was unable to perform a stat on the file - * APR_ENOPOOL APR was not provided a pool with which to allocate memory - * APR_EBADDATE APR was given an invalid date - * APR_EINVALSOCK APR was given an invalid socket - * APR_ENOPROC APR was not given a process structure - * APR_ENOTIME APR was not given a time structure - * APR_ENODIR APR was not given a directory structure - * APR_ENOLOCK APR was not given a lock structure - * APR_ENOPOLL APR was not given a poll structure - * APR_ENOSOCKET APR was not given a socket - * APR_ENOTHREAD APR was not given a thread structure - * APR_ENOTHDKEY APR was not given a thread key structure - * APR_ENOSHMAVAIL There is no more shared memory available - * APR_EDSOOPEN APR was unable to open the dso object. For more - * information call apr_dso_error(). - * APR_EGENERAL General failure (specific information not available) - * APR_EBADIP The specified IP address is invalid - * APR_EBADMASK The specified netmask is invalid - * APR_ESYMNOTFOUND Could not find the requested symbol - * </PRE> - * - * <PRE> - * <b>APR STATUS VALUES</b> - * APR_INCHILD Program is currently executing in the child - * APR_INPARENT Program is currently executing in the parent - * APR_DETACH The thread is detached - * APR_NOTDETACH The thread is not detached - * APR_CHILD_DONE The child has finished executing - * APR_CHILD_NOTDONE The child has not finished executing - * APR_TIMEUP The operation did not finish before the timeout - * APR_INCOMPLETE The operation was incomplete although some processing - * was performed and the results are partially valid - * APR_BADCH Getopt found an option not in the option string - * APR_BADARG Getopt found an option that is missing an argument - * and an argument was specified in the option string - * APR_EOF APR has encountered the end of the file - * APR_NOTFOUND APR was unable to find the socket in the poll structure - * APR_ANONYMOUS APR is using anonymous shared memory - * APR_FILEBASED APR is using a file name as the key to the shared memory - * APR_KEYBASED APR is using a shared key as the key to the shared memory - * APR_EINIT Ininitalizer value. If no option has been found, but - * the status variable requires a value, this should be used - * APR_ENOTIMPL The APR function has not been implemented on this - * platform, either because nobody has gotten to it yet, - * or the function is impossible on this platform. - * APR_EMISMATCH Two passwords do not match. - * APR_EABSOLUTE The given path was absolute. - * APR_ERELATIVE The given path was relative. - * APR_EINCOMPLETE The given path was neither relative nor absolute. - * APR_EABOVEROOT The given path was above the root path. - * APR_EBUSY The given lock was busy. - * APR_EPROC_UNKNOWN The given process wasn't recognized by APR - * </PRE> - * @{ - */ -/** @see APR_STATUS_IS_ENOSTAT */ -#define APR_ENOSTAT (APR_OS_START_ERROR + 1) -/** @see APR_STATUS_IS_ENOPOOL */ -#define APR_ENOPOOL (APR_OS_START_ERROR + 2) -/* empty slot: +3 */ -/** @see APR_STATUS_IS_EBADDATE */ -#define APR_EBADDATE (APR_OS_START_ERROR + 4) -/** @see APR_STATUS_IS_EINVALSOCK */ -#define APR_EINVALSOCK (APR_OS_START_ERROR + 5) -/** @see APR_STATUS_IS_ENOPROC */ -#define APR_ENOPROC (APR_OS_START_ERROR + 6) -/** @see APR_STATUS_IS_ENOTIME */ -#define APR_ENOTIME (APR_OS_START_ERROR + 7) -/** @see APR_STATUS_IS_ENODIR */ -#define APR_ENODIR (APR_OS_START_ERROR + 8) -/** @see APR_STATUS_IS_ENOLOCK */ -#define APR_ENOLOCK (APR_OS_START_ERROR + 9) -/** @see APR_STATUS_IS_ENOPOLL */ -#define APR_ENOPOLL (APR_OS_START_ERROR + 10) -/** @see APR_STATUS_IS_ENOSOCKET */ -#define APR_ENOSOCKET (APR_OS_START_ERROR + 11) -/** @see APR_STATUS_IS_ENOTHREAD */ -#define APR_ENOTHREAD (APR_OS_START_ERROR + 12) -/** @see APR_STATUS_IS_ENOTHDKEY */ -#define APR_ENOTHDKEY (APR_OS_START_ERROR + 13) -/** @see APR_STATUS_IS_EGENERAL */ -#define APR_EGENERAL (APR_OS_START_ERROR + 14) -/** @see APR_STATUS_IS_ENOSHMAVAIL */ -#define APR_ENOSHMAVAIL (APR_OS_START_ERROR + 15) -/** @see APR_STATUS_IS_EBADIP */ -#define APR_EBADIP (APR_OS_START_ERROR + 16) -/** @see APR_STATUS_IS_EBADMASK */ -#define APR_EBADMASK (APR_OS_START_ERROR + 17) -/* empty slot: +18 */ -/** @see APR_STATUS_IS_EDSOPEN */ -#define APR_EDSOOPEN (APR_OS_START_ERROR + 19) -/** @see APR_STATUS_IS_EABSOLUTE */ -#define APR_EABSOLUTE (APR_OS_START_ERROR + 20) -/** @see APR_STATUS_IS_ERELATIVE */ -#define APR_ERELATIVE (APR_OS_START_ERROR + 21) -/** @see APR_STATUS_IS_EINCOMPLETE */ -#define APR_EINCOMPLETE (APR_OS_START_ERROR + 22) -/** @see APR_STATUS_IS_EABOVEROOT */ -#define APR_EABOVEROOT (APR_OS_START_ERROR + 23) -/** @see APR_STATUS_IS_EBADPATH */ -#define APR_EBADPATH (APR_OS_START_ERROR + 24) -/** @see APR_STATUS_IS_EPATHWILD */ -#define APR_EPATHWILD (APR_OS_START_ERROR + 25) -/** @see APR_STATUS_IS_ESYMNOTFOUND */ -#define APR_ESYMNOTFOUND (APR_OS_START_ERROR + 26) -/** @see APR_STATUS_IS_EPROC_UNKNOWN */ -#define APR_EPROC_UNKNOWN (APR_OS_START_ERROR + 27) -/** @see APR_STATUS_IS_ENOTENOUGHENTROPY */ -#define APR_ENOTENOUGHENTROPY (APR_OS_START_ERROR + 28) -/** @} */ - -/** - * @defgroup APR_STATUS_IS Status Value Tests - * @warning For any particular error condition, more than one of these tests - * may match. This is because platform-specific error codes may not - * always match the semantics of the POSIX codes these tests (and the - * corresponding APR error codes) are named after. A notable example - * are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on - * Win32 platforms. The programmer should always be aware of this and - * adjust the order of the tests accordingly. - * @{ - */ -/** - * APR was unable to perform a stat on the file - * @warning always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ENOSTAT(s) ((s) == APR_ENOSTAT) -/** - * APR was not provided a pool with which to allocate memory - * @warning always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ENOPOOL(s) ((s) == APR_ENOPOOL) -/** APR was given an invalid date */ -#define APR_STATUS_IS_EBADDATE(s) ((s) == APR_EBADDATE) -/** APR was given an invalid socket */ -#define APR_STATUS_IS_EINVALSOCK(s) ((s) == APR_EINVALSOCK) -/** APR was not given a process structure */ -#define APR_STATUS_IS_ENOPROC(s) ((s) == APR_ENOPROC) -/** APR was not given a time structure */ -#define APR_STATUS_IS_ENOTIME(s) ((s) == APR_ENOTIME) -/** APR was not given a directory structure */ -#define APR_STATUS_IS_ENODIR(s) ((s) == APR_ENODIR) -/** APR was not given a lock structure */ -#define APR_STATUS_IS_ENOLOCK(s) ((s) == APR_ENOLOCK) -/** APR was not given a poll structure */ -#define APR_STATUS_IS_ENOPOLL(s) ((s) == APR_ENOPOLL) -/** APR was not given a socket */ -#define APR_STATUS_IS_ENOSOCKET(s) ((s) == APR_ENOSOCKET) -/** APR was not given a thread structure */ -#define APR_STATUS_IS_ENOTHREAD(s) ((s) == APR_ENOTHREAD) -/** APR was not given a thread key structure */ -#define APR_STATUS_IS_ENOTHDKEY(s) ((s) == APR_ENOTHDKEY) -/** Generic Error which can not be put into another spot */ -#define APR_STATUS_IS_EGENERAL(s) ((s) == APR_EGENERAL) -/** There is no more shared memory available */ -#define APR_STATUS_IS_ENOSHMAVAIL(s) ((s) == APR_ENOSHMAVAIL) -/** The specified IP address is invalid */ -#define APR_STATUS_IS_EBADIP(s) ((s) == APR_EBADIP) -/** The specified netmask is invalid */ -#define APR_STATUS_IS_EBADMASK(s) ((s) == APR_EBADMASK) -/* empty slot: +18 */ -/** - * APR was unable to open the dso object. - * For more information call apr_dso_error(). - */ -#if defined(WIN32) -#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN \ - || APR_TO_OS_ERROR(s) == ERROR_MOD_NOT_FOUND) -#else -#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN) -#endif -/** The given path was absolute. */ -#define APR_STATUS_IS_EABSOLUTE(s) ((s) == APR_EABSOLUTE) -/** The given path was relative. */ -#define APR_STATUS_IS_ERELATIVE(s) ((s) == APR_ERELATIVE) -/** The given path was neither relative nor absolute. */ -#define APR_STATUS_IS_EINCOMPLETE(s) ((s) == APR_EINCOMPLETE) -/** The given path was above the root path. */ -#define APR_STATUS_IS_EABOVEROOT(s) ((s) == APR_EABOVEROOT) -/** The given path was bad. */ -#define APR_STATUS_IS_EBADPATH(s) ((s) == APR_EBADPATH) -/** The given path contained wildcards. */ -#define APR_STATUS_IS_EPATHWILD(s) ((s) == APR_EPATHWILD) -/** Could not find the requested symbol. - * For more information call apr_dso_error(). - */ -#if defined(WIN32) -#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND \ - || APR_TO_OS_ERROR(s) == ERROR_PROC_NOT_FOUND) -#else -#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND) -#endif -/** The given process was not recognized by APR. */ -#define APR_STATUS_IS_EPROC_UNKNOWN(s) ((s) == APR_EPROC_UNKNOWN) - -/** APR could not gather enough entropy to continue. */ -#define APR_STATUS_IS_ENOTENOUGHENTROPY(s) ((s) == APR_ENOTENOUGHENTROPY) - -/** @} */ - -/** - * @addtogroup APR_Error - * @{ - */ -/** @see APR_STATUS_IS_INCHILD */ -#define APR_INCHILD (APR_OS_START_STATUS + 1) -/** @see APR_STATUS_IS_INPARENT */ -#define APR_INPARENT (APR_OS_START_STATUS + 2) -/** @see APR_STATUS_IS_DETACH */ -#define APR_DETACH (APR_OS_START_STATUS + 3) -/** @see APR_STATUS_IS_NOTDETACH */ -#define APR_NOTDETACH (APR_OS_START_STATUS + 4) -/** @see APR_STATUS_IS_CHILD_DONE */ -#define APR_CHILD_DONE (APR_OS_START_STATUS + 5) -/** @see APR_STATUS_IS_CHILD_NOTDONE */ -#define APR_CHILD_NOTDONE (APR_OS_START_STATUS + 6) -/** @see APR_STATUS_IS_TIMEUP */ -#define APR_TIMEUP (APR_OS_START_STATUS + 7) -/** @see APR_STATUS_IS_INCOMPLETE */ -#define APR_INCOMPLETE (APR_OS_START_STATUS + 8) -/* empty slot: +9 */ -/* empty slot: +10 */ -/* empty slot: +11 */ -/** @see APR_STATUS_IS_BADCH */ -#define APR_BADCH (APR_OS_START_STATUS + 12) -/** @see APR_STATUS_IS_BADARG */ -#define APR_BADARG (APR_OS_START_STATUS + 13) -/** @see APR_STATUS_IS_EOF */ -#define APR_EOF (APR_OS_START_STATUS + 14) -/** @see APR_STATUS_IS_NOTFOUND */ -#define APR_NOTFOUND (APR_OS_START_STATUS + 15) -/* empty slot: +16 */ -/* empty slot: +17 */ -/* empty slot: +18 */ -/** @see APR_STATUS_IS_ANONYMOUS */ -#define APR_ANONYMOUS (APR_OS_START_STATUS + 19) -/** @see APR_STATUS_IS_FILEBASED */ -#define APR_FILEBASED (APR_OS_START_STATUS + 20) -/** @see APR_STATUS_IS_KEYBASED */ -#define APR_KEYBASED (APR_OS_START_STATUS + 21) -/** @see APR_STATUS_IS_EINIT */ -#define APR_EINIT (APR_OS_START_STATUS + 22) -/** @see APR_STATUS_IS_ENOTIMPL */ -#define APR_ENOTIMPL (APR_OS_START_STATUS + 23) -/** @see APR_STATUS_IS_EMISMATCH */ -#define APR_EMISMATCH (APR_OS_START_STATUS + 24) -/** @see APR_STATUS_IS_EBUSY */ -#define APR_EBUSY (APR_OS_START_STATUS + 25) -/** @} */ - -/** - * @addtogroup APR_STATUS_IS - * @{ - */ -/** - * Program is currently executing in the child - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code */ -#define APR_STATUS_IS_INCHILD(s) ((s) == APR_INCHILD) -/** - * Program is currently executing in the parent - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_INPARENT(s) ((s) == APR_INPARENT) -/** - * The thread is detached - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_DETACH(s) ((s) == APR_DETACH) -/** - * The thread is not detached - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_NOTDETACH(s) ((s) == APR_NOTDETACH) -/** - * The child has finished executing - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_CHILD_DONE(s) ((s) == APR_CHILD_DONE) -/** - * The child has not finished executing - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_CHILD_NOTDONE(s) ((s) == APR_CHILD_NOTDONE) -/** - * The operation did not finish before the timeout - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP) -/** - * The operation was incomplete although some processing was performed - * and the results are partially valid. - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_INCOMPLETE(s) ((s) == APR_INCOMPLETE) -/* empty slot: +9 */ -/* empty slot: +10 */ -/* empty slot: +11 */ -/** - * Getopt found an option not in the option string - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_BADCH(s) ((s) == APR_BADCH) -/** - * Getopt found an option not in the option string and an argument was - * specified in the option string - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_BADARG(s) ((s) == APR_BADARG) -/** - * APR has encountered the end of the file - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EOF(s) ((s) == APR_EOF) -/** - * APR was unable to find the socket in the poll structure - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_NOTFOUND(s) ((s) == APR_NOTFOUND) -/* empty slot: +16 */ -/* empty slot: +17 */ -/* empty slot: +18 */ -/** - * APR is using anonymous shared memory - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ANONYMOUS(s) ((s) == APR_ANONYMOUS) -/** - * APR is using a file name as the key to the shared memory - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_FILEBASED(s) ((s) == APR_FILEBASED) -/** - * APR is using a shared key as the key to the shared memory - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_KEYBASED(s) ((s) == APR_KEYBASED) -/** - * Ininitalizer value. If no option has been found, but - * the status variable requires a value, this should be used - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EINIT(s) ((s) == APR_EINIT) -/** - * The APR function has not been implemented on this - * platform, either because nobody has gotten to it yet, - * or the function is impossible on this platform. - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ENOTIMPL(s) ((s) == APR_ENOTIMPL) -/** - * Two passwords do not match. - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EMISMATCH(s) ((s) == APR_EMISMATCH) -/** - * The given lock was busy - * @warning always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EBUSY(s) ((s) == APR_EBUSY) - -/** @} */ - -/** - * @addtogroup APR_Error APR Error Values - * @{ - */ -/* APR CANONICAL ERROR VALUES */ -/** @see APR_STATUS_IS_EACCES */ -#ifdef EACCES -#define APR_EACCES EACCES -#else -#define APR_EACCES (APR_OS_START_CANONERR + 1) -#endif - -/** @see APR_STATUS_IS_EXIST */ -#ifdef EEXIST -#define APR_EEXIST EEXIST -#else -#define APR_EEXIST (APR_OS_START_CANONERR + 2) -#endif - -/** @see APR_STATUS_IS_ENAMETOOLONG */ -#ifdef ENAMETOOLONG -#define APR_ENAMETOOLONG ENAMETOOLONG -#else -#define APR_ENAMETOOLONG (APR_OS_START_CANONERR + 3) -#endif - -/** @see APR_STATUS_IS_ENOENT */ -#ifdef ENOENT -#define APR_ENOENT ENOENT -#else -#define APR_ENOENT (APR_OS_START_CANONERR + 4) -#endif - -/** @see APR_STATUS_IS_ENOTDIR */ -#ifdef ENOTDIR -#define APR_ENOTDIR ENOTDIR -#else -#define APR_ENOTDIR (APR_OS_START_CANONERR + 5) -#endif - -/** @see APR_STATUS_IS_ENOSPC */ -#ifdef ENOSPC -#define APR_ENOSPC ENOSPC -#else -#define APR_ENOSPC (APR_OS_START_CANONERR + 6) -#endif - -/** @see APR_STATUS_IS_ENOMEM */ -#ifdef ENOMEM -#define APR_ENOMEM ENOMEM -#else -#define APR_ENOMEM (APR_OS_START_CANONERR + 7) -#endif - -/** @see APR_STATUS_IS_EMFILE */ -#ifdef EMFILE -#define APR_EMFILE EMFILE -#else -#define APR_EMFILE (APR_OS_START_CANONERR + 8) -#endif - -/** @see APR_STATUS_IS_ENFILE */ -#ifdef ENFILE -#define APR_ENFILE ENFILE -#else -#define APR_ENFILE (APR_OS_START_CANONERR + 9) -#endif - -/** @see APR_STATUS_IS_EBADF */ -#ifdef EBADF -#define APR_EBADF EBADF -#else -#define APR_EBADF (APR_OS_START_CANONERR + 10) -#endif - -/** @see APR_STATUS_IS_EINVAL */ -#ifdef EINVAL -#define APR_EINVAL EINVAL -#else -#define APR_EINVAL (APR_OS_START_CANONERR + 11) -#endif - -/** @see APR_STATUS_IS_ESPIPE */ -#ifdef ESPIPE -#define APR_ESPIPE ESPIPE -#else -#define APR_ESPIPE (APR_OS_START_CANONERR + 12) -#endif - -/** - * @see APR_STATUS_IS_EAGAIN - * @warning use APR_STATUS_IS_EAGAIN instead of just testing this value - */ -#ifdef EAGAIN -#define APR_EAGAIN EAGAIN -#elif defined(EWOULDBLOCK) -#define APR_EAGAIN EWOULDBLOCK -#else -#define APR_EAGAIN (APR_OS_START_CANONERR + 13) -#endif - -/** @see APR_STATUS_IS_EINTR */ -#ifdef EINTR -#define APR_EINTR EINTR -#else -#define APR_EINTR (APR_OS_START_CANONERR + 14) -#endif - -/** @see APR_STATUS_IS_ENOTSOCK */ -#ifdef ENOTSOCK -#define APR_ENOTSOCK ENOTSOCK -#else -#define APR_ENOTSOCK (APR_OS_START_CANONERR + 15) -#endif - -/** @see APR_STATUS_IS_ECONNREFUSED */ -#ifdef ECONNREFUSED -#define APR_ECONNREFUSED ECONNREFUSED -#else -#define APR_ECONNREFUSED (APR_OS_START_CANONERR + 16) -#endif - -/** @see APR_STATUS_IS_EINPROGRESS */ -#ifdef EINPROGRESS -#define APR_EINPROGRESS EINPROGRESS -#else -#define APR_EINPROGRESS (APR_OS_START_CANONERR + 17) -#endif - -/** - * @see APR_STATUS_IS_ECONNABORTED - * @warning use APR_STATUS_IS_ECONNABORTED instead of just testing this value - */ - -#ifdef ECONNABORTED -#define APR_ECONNABORTED ECONNABORTED -#else -#define APR_ECONNABORTED (APR_OS_START_CANONERR + 18) -#endif - -/** @see APR_STATUS_IS_ECONNRESET */ -#ifdef ECONNRESET -#define APR_ECONNRESET ECONNRESET -#else -#define APR_ECONNRESET (APR_OS_START_CANONERR + 19) -#endif - -/** @see APR_STATUS_IS_ETIMEDOUT - * @deprecated */ -#ifdef ETIMEDOUT -#define APR_ETIMEDOUT ETIMEDOUT -#else -#define APR_ETIMEDOUT (APR_OS_START_CANONERR + 20) -#endif - -/** @see APR_STATUS_IS_EHOSTUNREACH */ -#ifdef EHOSTUNREACH -#define APR_EHOSTUNREACH EHOSTUNREACH -#else -#define APR_EHOSTUNREACH (APR_OS_START_CANONERR + 21) -#endif - -/** @see APR_STATUS_IS_ENETUNREACH */ -#ifdef ENETUNREACH -#define APR_ENETUNREACH ENETUNREACH -#else -#define APR_ENETUNREACH (APR_OS_START_CANONERR + 22) -#endif - -/** @see APR_STATUS_IS_EFTYPE */ -#ifdef EFTYPE -#define APR_EFTYPE EFTYPE -#else -#define APR_EFTYPE (APR_OS_START_CANONERR + 23) -#endif - -/** @see APR_STATUS_IS_EPIPE */ -#ifdef EPIPE -#define APR_EPIPE EPIPE -#else -#define APR_EPIPE (APR_OS_START_CANONERR + 24) -#endif - -/** @see APR_STATUS_IS_EXDEV */ -#ifdef EXDEV -#define APR_EXDEV EXDEV -#else -#define APR_EXDEV (APR_OS_START_CANONERR + 25) -#endif - -/** @see APR_STATUS_IS_ENOTEMPTY */ -#ifdef ENOTEMPTY -#define APR_ENOTEMPTY ENOTEMPTY -#else -#define APR_ENOTEMPTY (APR_OS_START_CANONERR + 26) -#endif - -/** @} */ - -#if defined(OS2) && !defined(DOXYGEN) - -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -#define INCL_DOSERRORS -#define INCL_DOS - -/* Leave these undefined. - * OS2 doesn't rely on the errno concept. - * The API calls always return a result codes which - * should be filtered through APR_FROM_OS_ERROR(). - * - * #define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) - * #define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) - */ - -/* A special case, only socket calls require this; - */ -#define apr_get_netos_error() (APR_FROM_OS_ERROR(errno)) -#define apr_set_netos_error(e) (errno = APR_TO_OS_ERROR(e)) - -/* And this needs to be greped away for good: - */ -#define APR_OS2_STATUS(e) (APR_FROM_OS_ERROR(e)) - -/* These can't sit in a private header, so in spite of the extra size, - * they need to be made available here. - */ -#define SOCBASEERR 10000 -#define SOCEPERM (SOCBASEERR+1) /* Not owner */ -#define SOCESRCH (SOCBASEERR+3) /* No such process */ -#define SOCEINTR (SOCBASEERR+4) /* Interrupted system call */ -#define SOCENXIO (SOCBASEERR+6) /* No such device or address */ -#define SOCEBADF (SOCBASEERR+9) /* Bad file number */ -#define SOCEACCES (SOCBASEERR+13) /* Permission denied */ -#define SOCEFAULT (SOCBASEERR+14) /* Bad address */ -#define SOCEINVAL (SOCBASEERR+22) /* Invalid argument */ -#define SOCEMFILE (SOCBASEERR+24) /* Too many open files */ -#define SOCEPIPE (SOCBASEERR+32) /* Broken pipe */ -#define SOCEOS2ERR (SOCBASEERR+100) /* OS/2 Error */ -#define SOCEWOULDBLOCK (SOCBASEERR+35) /* Operation would block */ -#define SOCEINPROGRESS (SOCBASEERR+36) /* Operation now in progress */ -#define SOCEALREADY (SOCBASEERR+37) /* Operation already in progress */ -#define SOCENOTSOCK (SOCBASEERR+38) /* Socket operation on non-socket */ -#define SOCEDESTADDRREQ (SOCBASEERR+39) /* Destination address required */ -#define SOCEMSGSIZE (SOCBASEERR+40) /* Message too long */ -#define SOCEPROTOTYPE (SOCBASEERR+41) /* Protocol wrong type for socket */ -#define SOCENOPROTOOPT (SOCBASEERR+42) /* Protocol not available */ -#define SOCEPROTONOSUPPORT (SOCBASEERR+43) /* Protocol not supported */ -#define SOCESOCKTNOSUPPORT (SOCBASEERR+44) /* Socket type not supported */ -#define SOCEOPNOTSUPP (SOCBASEERR+45) /* Operation not supported on socket */ -#define SOCEPFNOSUPPORT (SOCBASEERR+46) /* Protocol family not supported */ -#define SOCEAFNOSUPPORT (SOCBASEERR+47) /* Address family not supported by protocol family */ -#define SOCEADDRINUSE (SOCBASEERR+48) /* Address already in use */ -#define SOCEADDRNOTAVAIL (SOCBASEERR+49) /* Can't assign requested address */ -#define SOCENETDOWN (SOCBASEERR+50) /* Network is down */ -#define SOCENETUNREACH (SOCBASEERR+51) /* Network is unreachable */ -#define SOCENETRESET (SOCBASEERR+52) /* Network dropped connection on reset */ -#define SOCECONNABORTED (SOCBASEERR+53) /* Software caused connection abort */ -#define SOCECONNRESET (SOCBASEERR+54) /* Connection reset by peer */ -#define SOCENOBUFS (SOCBASEERR+55) /* No buffer space available */ -#define SOCEISCONN (SOCBASEERR+56) /* Socket is already connected */ -#define SOCENOTCONN (SOCBASEERR+57) /* Socket is not connected */ -#define SOCESHUTDOWN (SOCBASEERR+58) /* Can't send after socket shutdown */ -#define SOCETOOMANYREFS (SOCBASEERR+59) /* Too many references: can't splice */ -#define SOCETIMEDOUT (SOCBASEERR+60) /* Connection timed out */ -#define SOCECONNREFUSED (SOCBASEERR+61) /* Connection refused */ -#define SOCELOOP (SOCBASEERR+62) /* Too many levels of symbolic links */ -#define SOCENAMETOOLONG (SOCBASEERR+63) /* File name too long */ -#define SOCEHOSTDOWN (SOCBASEERR+64) /* Host is down */ -#define SOCEHOSTUNREACH (SOCBASEERR+65) /* No route to host */ -#define SOCENOTEMPTY (SOCBASEERR+66) /* Directory not empty */ - -/* APR CANONICAL ERROR TESTS */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ - || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ - || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ - || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ - || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ - || (s) == APR_OS_START_SYSERR + SOCENAMETOOLONG) -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES \ - || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED) -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ - || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ - || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE) -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION) -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ - || (s) == APR_OS_START_SYSERR + SOCEWOULDBLOCK \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION) -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ - || (s) == APR_OS_START_SYSERR + SOCEINTR) -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ - || (s) == APR_OS_START_SYSERR + SOCENOTSOCK) -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ - || (s) == APR_OS_START_SYSERR + SOCECONNREFUSED) -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ - || (s) == APR_OS_START_SYSERR + SOCEINPROGRESS) -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == APR_OS_START_SYSERR + SOCECONNABORTED) -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ - || (s) == APR_OS_START_SYSERR + SOCECONNRESET) -/* XXX deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) -#undef APR_STATUS_IS_TIMEUP -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ - || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ - || (s) == APR_OS_START_SYSERR + SOCEHOSTUNREACH) -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ - || (s) == APR_OS_START_SYSERR + SOCENETUNREACH) -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE \ - || (s) == APR_OS_START_SYSERR + SOCEPIPE) -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ - || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) - -/* - Sorry, too tired to wrap this up for OS2... feel free to - fit the following into their best matches. - - { ERROR_NO_SIGNAL_SENT, ESRCH }, - { SOCEALREADY, EALREADY }, - { SOCEDESTADDRREQ, EDESTADDRREQ }, - { SOCEMSGSIZE, EMSGSIZE }, - { SOCEPROTOTYPE, EPROTOTYPE }, - { SOCENOPROTOOPT, ENOPROTOOPT }, - { SOCEPROTONOSUPPORT, EPROTONOSUPPORT }, - { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT }, - { SOCEOPNOTSUPP, EOPNOTSUPP }, - { SOCEPFNOSUPPORT, EPFNOSUPPORT }, - { SOCEAFNOSUPPORT, EAFNOSUPPORT }, - { SOCEADDRINUSE, EADDRINUSE }, - { SOCEADDRNOTAVAIL, EADDRNOTAVAIL }, - { SOCENETDOWN, ENETDOWN }, - { SOCENETRESET, ENETRESET }, - { SOCENOBUFS, ENOBUFS }, - { SOCEISCONN, EISCONN }, - { SOCENOTCONN, ENOTCONN }, - { SOCESHUTDOWN, ESHUTDOWN }, - { SOCETOOMANYREFS, ETOOMANYREFS }, - { SOCELOOP, ELOOP }, - { SOCEHOSTDOWN, EHOSTDOWN }, - { SOCENOTEMPTY, ENOTEMPTY }, - { SOCEPIPE, EPIPE } -*/ - -#elif defined(WIN32) && !defined(DOXYGEN) /* !defined(OS2) */ - -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -#define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) -#define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) - -/* A special case, only socket calls require this: - */ -#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) -#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) - -/* APR CANONICAL ERROR TESTS */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ - || (s) == APR_OS_START_SYSERR + ERROR_CANNOT_MAKE \ - || (s) == APR_OS_START_SYSERR + ERROR_CURRENT_DIRECTORY \ - || (s) == APR_OS_START_SYSERR + ERROR_DRIVE_LOCKED \ - || (s) == APR_OS_START_SYSERR + ERROR_FAIL_I24 \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_FAILED \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_LOCKED \ - || (s) == APR_OS_START_SYSERR + ERROR_NETWORK_ACCESS_DENIED \ - || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ - || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS) -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ - || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ - || (s) == APR_OS_START_SYSERR + WSAENAMETOOLONG) -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES) -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR \ - || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_NETPATH \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_NET_NAME \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_PATHNAME \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DRIVE) -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ - || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM \ - || (s) == APR_OS_START_SYSERR + ERROR_ARENA_TRASHED \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_MEMORY \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_BLOCK \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_QUOTA \ - || (s) == APR_OS_START_SYSERR + ERROR_OUTOFMEMORY) -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ - || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_TARGET_HANDLE) -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_ACCESS \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DATA \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ - || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_SEEK_ON_DEVICE \ - || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_PROC_SLOTS \ - || (s) == APR_OS_START_SYSERR + ERROR_NESTING_NOT_ALLOWED \ - || (s) == APR_OS_START_SYSERR + ERROR_MAX_THRDS_REACHED \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ - || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ - || (s) == APR_OS_START_SYSERR + WSAEINTR) -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ - || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ - || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ - || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ - || (s) == APR_OS_START_SYSERR + ERROR_NETNAME_DELETED \ - || (s) == APR_OS_START_SYSERR + WSAECONNRESET) -/* XXX deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#undef APR_STATUS_IS_TIMEUP -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE \ - || (s) == APR_OS_START_SYSERR + ERROR_EXE_MACHINE_TYPE_MISMATCH \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DLL \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_MODULETYPE \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_EXE_FORMAT \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_EXE_SIGNATURE \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_CORRUPT \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_FORMAT) -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE) -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ - || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY) - -#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */ - -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -#define apr_get_os_error() (errno) -#define apr_set_os_error(e) (errno = (e)) - -/* A special case, only socket calls require this: */ -#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) -#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) - -/* APR CANONICAL ERROR TESTS */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) - -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == EWOULDBLOCK \ - || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ - || (s) == APR_OS_START_SYSERR + WSAEINTR) -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ - || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ - || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ - || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ - || (s) == APR_OS_START_SYSERR + WSAECONNRESET) -/* XXX deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#undef APR_STATUS_IS_TIMEUP -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) -#define APR_STATUS_IS_ENETDOWN(s) ((s) == APR_OS_START_SYSERR + WSAENETDOWN) -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY) - -#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ - -/* - * os error codes are clib error codes - */ -#define APR_FROM_OS_ERROR(e) (e) -#define APR_TO_OS_ERROR(e) (e) - -#define apr_get_os_error() (errno) -#define apr_set_os_error(e) (errno = (e)) - -/* A special case, only socket calls require this: - */ -#define apr_get_netos_error() (errno) -#define apr_set_netos_error(e) (errno = (e)) - -/** - * @addtogroup APR_STATUS_IS - * @{ - */ - -/** permission denied */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) -/** file exists */ -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) -/** path name is too long */ -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) -/** - * no such file or directory - * @remark - * EMVSCATLG can be returned by the automounter on z/OS for - * paths which do not exist. - */ -#ifdef EMVSCATLG -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ - || (s) == EMVSCATLG) -#else -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) -#endif -/** not a directory */ -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) -/** no space left on device */ -#ifdef EDQUOT -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ - || (s) == EDQUOT) -#else -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) -#endif -/** not enough memory */ -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) -/** too many open files */ -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) -/** file table overflow */ -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -/** bad file # */ -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) -/** invalid argument */ -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) -/** illegal seek */ -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) - -/** operation would block */ -#if !defined(EWOULDBLOCK) || !defined(EAGAIN) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) -#elif (EWOULDBLOCK == EAGAIN) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) -#else -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == EWOULDBLOCK) -#endif - -/** interrupted system call */ -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR) -/** socket operation on a non-socket */ -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK) -/** Connection Refused */ -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED) -/** operation now in progress */ -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS) - -/** - * Software caused connection abort - * @remark - * EPROTO on certain older kernels really means ECONNABORTED, so we need to - * ignore it for them. See discussion in new-httpd archives nh.9701 & nh.9603 - * - * There is potentially a bug in Solaris 2.x x<6, and other boxes that - * implement tcp sockets in userland (i.e. on top of STREAMS). On these - * systems, EPROTO can actually result in a fatal loop. See PR#981 for - * example. It's hard to handle both uses of EPROTO. - */ -#ifdef EPROTO -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == EPROTO) -#else -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED) -#endif - -/** Connection Reset by peer */ -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET) -/** Operation timed out - * @deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT) -/** no route to host */ -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH) -/** network is unreachable */ -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH) -/** inappropiate file type or format */ -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) -/** broken pipe */ -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) -/** cross device link */ -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) -/** Directory Not Empty */ -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY || \ - (s) == APR_EEXIST) -/** @} */ - -#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* ! APR_ERRNO_H */ -#ifndef _LINUX_ERRNO_H -#define _LINUX_ERRNO_H - -#include <asm/errno.h> - -#ifdef __KERNEL__ - -/* Should never be seen by user programs */ -#define ERESTARTSYS 512 -#define ERESTARTNOINTR 513 -#define ERESTARTNOHAND 514 /* restart if no handler.. */ -#define ENOIOCTLCMD 515 /* No ioctl command */ -#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ - -/* Defined for the NFSv3 protocol */ -#define EBADHANDLE 521 /* Illegal NFS file handle */ -#define ENOTSYNC 522 /* Update synchronization mismatch */ -#define EBADCOOKIE 523 /* Cookie is stale */ -#define ENOTSUPP 524 /* Operation is not supported */ -#define ETOOSMALL 525 /* Buffer or request is too small */ -#define ESERVERFAULT 526 /* An untranslatable error occurred */ -#define EBADTYPE 527 /* Type not supported by server */ -#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ -#define EIOCBQUEUED 529 /* iocb queued, will get completion event */ -#define EIOCBRETRY 530 /* iocb queued, will trigger a retry */ - -#endif - -#endif -// Copyright (c) 1994 James Clark -// See the file COPYING for copying permission. - -#ifndef ErrnoMessageArg_INCLUDED -#define ErrnoMessageArg_INCLUDED 1 - -#include "MessageArg.h" -#include "rtti.h" - -#ifdef SP_NAMESPACE -namespace SP_NAMESPACE { -#endif - -class SP_API ErrnoMessageArg : public OtherMessageArg { - RTTI_CLASS -public: - ErrnoMessageArg(int errnum) : errno_(errnum) { } - MessageArg *copy() const; - // errno might be a macro so we must use a different name - int errnum() const; -private: - int errno_; -}; - -inline -int ErrnoMessageArg::errnum() const -{ - return errno_; -} - -#ifdef SP_NAMESPACE -} -#endif - -#endif /* not ErrnoMessageArg_INCLUDED */ -/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - * ISO C99 Standard: 7.5 Errors <errno.h> - */ - -#ifndef _ERRNO_H - -/* The includer defined __need_Emath if he wants only the definitions - of EDOM and ERANGE, and not everything else. */ -#ifndef __need_Emath -# define _ERRNO_H 1 -# include <features.h> -#endif - -__BEGIN_DECLS - -/* Get the error number constants from the system-specific file. - This file will test __need_Emath and _ERRNO_H. */ -#include <bits/errno.h> -#undef __need_Emath - -#ifdef _ERRNO_H - -/* Declare the `errno' variable, unless it's defined as a macro by - bits/errno.h. This is the case in GNU, where it is a per-thread - variable. This redeclaration using the macro still works, but it - will be a function declaration without a prototype and may trigger - a -Wstrict-prototypes warning. */ -#ifndef errno -extern int errno; -#endif - -#ifdef __USE_GNU - -/* The full and simple forms of the name with which the program was - invoked. These variables are set up automatically at startup based on - the value of ARGV[0] (this works only if you use GNU ld). */ -extern char *program_invocation_name, *program_invocation_short_name; -#endif /* __USE_GNU */ -#endif /* _ERRNO_H */ - -__END_DECLS - -#endif /* _ERRNO_H */ - -/* The Hurd <bits/errno.h> defines `error_t' as an enumerated type so - that printing `error_t' values in the debugger shows the names. We - might need this definition sometimes even if this file was included - before. */ -#if defined __USE_GNU || defined __need_error_t -# ifndef __error_t_defined -typedef int error_t; -# define __error_t_defined 1 -# endif -# undef __need_error_t -#endif -#ifndef _I386_ERRNO_H -#define _I386_ERRNO_H - -#include <asm-generic/errno.h> - -#endif -#ifndef _ASM_GENERIC_ERRNO_BASE_H -#define _ASM_GENERIC_ERRNO_BASE_H - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ - -#endif -#ifndef _ASM_GENERIC_ERRNO_H -#define _ASM_GENERIC_ERRNO_H - -#include <asm-generic/errno-base.h> - -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ -#define ECANCELED 125 /* Operation Canceled */ -#define ENOKEY 126 /* Required key not available */ -#define EKEYEXPIRED 127 /* Key has expired */ -#define EKEYREVOKED 128 /* Key has been revoked */ -#define EKEYREJECTED 129 /* Key was rejected by service */ - -/* for robust mutexes */ -#define EOWNERDEAD 130 /* Owner died */ -#define ENOTRECOVERABLE 131 /* State not recoverable */ - -#endif diff --git a/doc/errno.list.macosx.txt b/doc/errno.list.macosx.txt deleted file mode 100644 index 728753ac793..00000000000 --- a/doc/errno.list.macosx.txt +++ /dev/null @@ -1,1513 +0,0 @@ -/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as - * applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef APR_ERRNO_H -#define APR_ERRNO_H - -/** - * @file apr_errno.h - * @brief APR Error Codes - */ - -#include "apr.h" - -#if APR_HAVE_ERRNO_H -#include <errno.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup apr_errno Error Codes - * @ingroup APR - * @{ - */ - -/** - * Type for specifying an error or status code. - */ -typedef int apr_status_t; - -/** - * Return a human readable string describing the specified error. - * @param statcode The error code the get a string for. - * @param buf A buffer to hold the error string. - * @param bufsize Size of the buffer to hold the string. - */ -APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, - apr_size_t bufsize); - -#if defined(DOXYGEN) -/** - * @def APR_FROM_OS_ERROR(os_err_type syserr) - * Fold a platform specific error into an apr_status_t code. - * @return apr_status_t - * @param e The platform os error code. - * @warning macro implementation; the syserr argument may be evaluated - * multiple times. - */ -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) - -/** - * @def APR_TO_OS_ERROR(apr_status_t statcode) - * @return os_err_type - * Fold an apr_status_t code back to the native platform defined error. - * @param e The apr_status_t folded platform os error code. - * @warning macro implementation; the statcode argument may be evaluated - * multiple times. If the statcode was not created by apr_get_os_error - * or APR_FROM_OS_ERROR, the results are undefined. - */ -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -/** @def apr_get_os_error() - * @return apr_status_t the last platform error, folded into apr_status_t, on most platforms - * @remark This retrieves errno, or calls a GetLastError() style function, and - * folds it with APR_FROM_OS_ERROR. Some platforms (such as OS2) have no - * such mechanism, so this call may be unsupported. Do NOT use this - * call for socket errors from socket, send, recv etc! - */ - -/** @def apr_set_os_error(e) - * Reset the last platform error, unfolded from an apr_status_t, on some platforms - * @param e The OS error folded in a prior call to APR_FROM_OS_ERROR() - * @warning This is a macro implementation; the statcode argument may be evaluated - * multiple times. If the statcode was not created by apr_get_os_error - * or APR_FROM_OS_ERROR, the results are undefined. This macro sets - * errno, or calls a SetLastError() style function, unfolding statcode - * with APR_TO_OS_ERROR. Some platforms (such as OS2) have no such - * mechanism, so this call may be unsupported. - */ - -/** @def apr_get_netos_error() - * Return the last socket error, folded into apr_status_t, on all platforms - * @remark This retrieves errno or calls a GetLastSocketError() style function, - * and folds it with APR_FROM_OS_ERROR. - */ - -/** @def apr_set_netos_error(e) - * Reset the last socket error, unfolded from an apr_status_t - * @param e The socket error folded in a prior call to APR_FROM_OS_ERROR() - * @warning This is a macro implementation; the statcode argument may be evaluated - * multiple times. If the statcode was not created by apr_get_os_error - * or APR_FROM_OS_ERROR, the results are undefined. This macro sets - * errno, or calls a WSASetLastError() style function, unfolding - * socketcode with APR_TO_OS_ERROR. - */ - -#endif /* defined(DOXYGEN) */ - -/** - * APR_OS_START_ERROR is where the APR specific error values start. - */ -#define APR_OS_START_ERROR 20000 -/** - * APR_OS_ERRSPACE_SIZE is the maximum number of errors you can fit - * into one of the error/status ranges below -- except for - * APR_OS_START_USERERR, which see. - */ -#define APR_OS_ERRSPACE_SIZE 50000 -/** - * APR_OS_START_STATUS is where the APR specific status codes start. - */ -#define APR_OS_START_STATUS (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE) -/** - * APR_OS_START_USERERR are reserved for applications that use APR that - * layer their own error codes along with APR's. Note that the - * error immediately following this one is set ten times farther - * away than usual, so that users of apr have a lot of room in - * which to declare custom error codes. - */ -#define APR_OS_START_USERERR (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE) -/** - * APR_OS_START_USEERR is obsolete, defined for compatibility only. - * Use APR_OS_START_USERERR instead. - */ -#define APR_OS_START_USEERR APR_OS_START_USERERR -/** - * APR_OS_START_CANONERR is where APR versions of errno values are defined - * on systems which don't have the corresponding errno. - */ -#define APR_OS_START_CANONERR (APR_OS_START_USERERR \ - + (APR_OS_ERRSPACE_SIZE * 10)) -/** - * APR_OS_START_EAIERR folds EAI_ error codes from getaddrinfo() into - * apr_status_t values. - */ -#define APR_OS_START_EAIERR (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE) -/** - * APR_OS_START_SYSERR folds platform-specific system error values into - * apr_status_t values. - */ -#define APR_OS_START_SYSERR (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE) - -/** no error. */ -#define APR_SUCCESS 0 - -/** - * @defgroup APR_Error APR Error Values - * <PRE> - * <b>APR ERROR VALUES</b> - * APR_ENOSTAT APR was unable to perform a stat on the file - * APR_ENOPOOL APR was not provided a pool with which to allocate memory - * APR_EBADDATE APR was given an invalid date - * APR_EINVALSOCK APR was given an invalid socket - * APR_ENOPROC APR was not given a process structure - * APR_ENOTIME APR was not given a time structure - * APR_ENODIR APR was not given a directory structure - * APR_ENOLOCK APR was not given a lock structure - * APR_ENOPOLL APR was not given a poll structure - * APR_ENOSOCKET APR was not given a socket - * APR_ENOTHREAD APR was not given a thread structure - * APR_ENOTHDKEY APR was not given a thread key structure - * APR_ENOSHMAVAIL There is no more shared memory available - * APR_EDSOOPEN APR was unable to open the dso object. For more - * information call apr_dso_error(). - * APR_EGENERAL General failure (specific information not available) - * APR_EBADIP The specified IP address is invalid - * APR_EBADMASK The specified netmask is invalid - * APR_ESYMNOTFOUND Could not find the requested symbol - * </PRE> - * - * <PRE> - * <b>APR STATUS VALUES</b> - * APR_INCHILD Program is currently executing in the child - * APR_INPARENT Program is currently executing in the parent - * APR_DETACH The thread is detached - * APR_NOTDETACH The thread is not detached - * APR_CHILD_DONE The child has finished executing - * APR_CHILD_NOTDONE The child has not finished executing - * APR_TIMEUP The operation did not finish before the timeout - * APR_INCOMPLETE The operation was incomplete although some processing - * was performed and the results are partially valid - * APR_BADCH Getopt found an option not in the option string - * APR_BADARG Getopt found an option that is missing an argument - * and an argument was specified in the option string - * APR_EOF APR has encountered the end of the file - * APR_NOTFOUND APR was unable to find the socket in the poll structure - * APR_ANONYMOUS APR is using anonymous shared memory - * APR_FILEBASED APR is using a file name as the key to the shared memory - * APR_KEYBASED APR is using a shared key as the key to the shared memory - * APR_EINIT Ininitalizer value. If no option has been found, but - * the status variable requires a value, this should be used - * APR_ENOTIMPL The APR function has not been implemented on this - * platform, either because nobody has gotten to it yet, - * or the function is impossible on this platform. - * APR_EMISMATCH Two passwords do not match. - * APR_EABSOLUTE The given path was absolute. - * APR_ERELATIVE The given path was relative. - * APR_EINCOMPLETE The given path was neither relative nor absolute. - * APR_EABOVEROOT The given path was above the root path. - * APR_EBUSY The given lock was busy. - * APR_EPROC_UNKNOWN The given process wasn't recognized by APR - * </PRE> - * @{ - */ -/** @see APR_STATUS_IS_ENOSTAT */ -#define APR_ENOSTAT (APR_OS_START_ERROR + 1) -/** @see APR_STATUS_IS_ENOPOOL */ -#define APR_ENOPOOL (APR_OS_START_ERROR + 2) -/* empty slot: +3 */ -/** @see APR_STATUS_IS_EBADDATE */ -#define APR_EBADDATE (APR_OS_START_ERROR + 4) -/** @see APR_STATUS_IS_EINVALSOCK */ -#define APR_EINVALSOCK (APR_OS_START_ERROR + 5) -/** @see APR_STATUS_IS_ENOPROC */ -#define APR_ENOPROC (APR_OS_START_ERROR + 6) -/** @see APR_STATUS_IS_ENOTIME */ -#define APR_ENOTIME (APR_OS_START_ERROR + 7) -/** @see APR_STATUS_IS_ENODIR */ -#define APR_ENODIR (APR_OS_START_ERROR + 8) -/** @see APR_STATUS_IS_ENOLOCK */ -#define APR_ENOLOCK (APR_OS_START_ERROR + 9) -/** @see APR_STATUS_IS_ENOPOLL */ -#define APR_ENOPOLL (APR_OS_START_ERROR + 10) -/** @see APR_STATUS_IS_ENOSOCKET */ -#define APR_ENOSOCKET (APR_OS_START_ERROR + 11) -/** @see APR_STATUS_IS_ENOTHREAD */ -#define APR_ENOTHREAD (APR_OS_START_ERROR + 12) -/** @see APR_STATUS_IS_ENOTHDKEY */ -#define APR_ENOTHDKEY (APR_OS_START_ERROR + 13) -/** @see APR_STATUS_IS_EGENERAL */ -#define APR_EGENERAL (APR_OS_START_ERROR + 14) -/** @see APR_STATUS_IS_ENOSHMAVAIL */ -#define APR_ENOSHMAVAIL (APR_OS_START_ERROR + 15) -/** @see APR_STATUS_IS_EBADIP */ -#define APR_EBADIP (APR_OS_START_ERROR + 16) -/** @see APR_STATUS_IS_EBADMASK */ -#define APR_EBADMASK (APR_OS_START_ERROR + 17) -/* empty slot: +18 */ -/** @see APR_STATUS_IS_EDSOPEN */ -#define APR_EDSOOPEN (APR_OS_START_ERROR + 19) -/** @see APR_STATUS_IS_EABSOLUTE */ -#define APR_EABSOLUTE (APR_OS_START_ERROR + 20) -/** @see APR_STATUS_IS_ERELATIVE */ -#define APR_ERELATIVE (APR_OS_START_ERROR + 21) -/** @see APR_STATUS_IS_EINCOMPLETE */ -#define APR_EINCOMPLETE (APR_OS_START_ERROR + 22) -/** @see APR_STATUS_IS_EABOVEROOT */ -#define APR_EABOVEROOT (APR_OS_START_ERROR + 23) -/** @see APR_STATUS_IS_EBADPATH */ -#define APR_EBADPATH (APR_OS_START_ERROR + 24) -/** @see APR_STATUS_IS_EPATHWILD */ -#define APR_EPATHWILD (APR_OS_START_ERROR + 25) -/** @see APR_STATUS_IS_ESYMNOTFOUND */ -#define APR_ESYMNOTFOUND (APR_OS_START_ERROR + 26) -/** @see APR_STATUS_IS_EPROC_UNKNOWN */ -#define APR_EPROC_UNKNOWN (APR_OS_START_ERROR + 27) -/** @see APR_STATUS_IS_ENOTENOUGHENTROPY */ -#define APR_ENOTENOUGHENTROPY (APR_OS_START_ERROR + 28) -/** @} */ - -/** - * @defgroup APR_STATUS_IS Status Value Tests - * @warning For any particular error condition, more than one of these tests - * may match. This is because platform-specific error codes may not - * always match the semantics of the POSIX codes these tests (and the - * corresponding APR error codes) are named after. A notable example - * are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on - * Win32 platforms. The programmer should always be aware of this and - * adjust the order of the tests accordingly. - * @{ - */ -/** - * APR was unable to perform a stat on the file - * @warning always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ENOSTAT(s) ((s) == APR_ENOSTAT) -/** - * APR was not provided a pool with which to allocate memory - * @warning always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ENOPOOL(s) ((s) == APR_ENOPOOL) -/** APR was given an invalid date */ -#define APR_STATUS_IS_EBADDATE(s) ((s) == APR_EBADDATE) -/** APR was given an invalid socket */ -#define APR_STATUS_IS_EINVALSOCK(s) ((s) == APR_EINVALSOCK) -/** APR was not given a process structure */ -#define APR_STATUS_IS_ENOPROC(s) ((s) == APR_ENOPROC) -/** APR was not given a time structure */ -#define APR_STATUS_IS_ENOTIME(s) ((s) == APR_ENOTIME) -/** APR was not given a directory structure */ -#define APR_STATUS_IS_ENODIR(s) ((s) == APR_ENODIR) -/** APR was not given a lock structure */ -#define APR_STATUS_IS_ENOLOCK(s) ((s) == APR_ENOLOCK) -/** APR was not given a poll structure */ -#define APR_STATUS_IS_ENOPOLL(s) ((s) == APR_ENOPOLL) -/** APR was not given a socket */ -#define APR_STATUS_IS_ENOSOCKET(s) ((s) == APR_ENOSOCKET) -/** APR was not given a thread structure */ -#define APR_STATUS_IS_ENOTHREAD(s) ((s) == APR_ENOTHREAD) -/** APR was not given a thread key structure */ -#define APR_STATUS_IS_ENOTHDKEY(s) ((s) == APR_ENOTHDKEY) -/** Generic Error which can not be put into another spot */ -#define APR_STATUS_IS_EGENERAL(s) ((s) == APR_EGENERAL) -/** There is no more shared memory available */ -#define APR_STATUS_IS_ENOSHMAVAIL(s) ((s) == APR_ENOSHMAVAIL) -/** The specified IP address is invalid */ -#define APR_STATUS_IS_EBADIP(s) ((s) == APR_EBADIP) -/** The specified netmask is invalid */ -#define APR_STATUS_IS_EBADMASK(s) ((s) == APR_EBADMASK) -/* empty slot: +18 */ -/** - * APR was unable to open the dso object. - * For more information call apr_dso_error(). - */ -#if defined(WIN32) -#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN \ - || APR_TO_OS_ERROR(s) == ERROR_MOD_NOT_FOUND) -#else -#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN) -#endif -/** The given path was absolute. */ -#define APR_STATUS_IS_EABSOLUTE(s) ((s) == APR_EABSOLUTE) -/** The given path was relative. */ -#define APR_STATUS_IS_ERELATIVE(s) ((s) == APR_ERELATIVE) -/** The given path was neither relative nor absolute. */ -#define APR_STATUS_IS_EINCOMPLETE(s) ((s) == APR_EINCOMPLETE) -/** The given path was above the root path. */ -#define APR_STATUS_IS_EABOVEROOT(s) ((s) == APR_EABOVEROOT) -/** The given path was bad. */ -#define APR_STATUS_IS_EBADPATH(s) ((s) == APR_EBADPATH) -/** The given path contained wildcards. */ -#define APR_STATUS_IS_EPATHWILD(s) ((s) == APR_EPATHWILD) -/** Could not find the requested symbol. - * For more information call apr_dso_error(). - */ -#if defined(WIN32) -#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND \ - || APR_TO_OS_ERROR(s) == ERROR_PROC_NOT_FOUND) -#else -#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND) -#endif -/** The given process was not recognized by APR. */ -#define APR_STATUS_IS_EPROC_UNKNOWN(s) ((s) == APR_EPROC_UNKNOWN) - -/** APR could not gather enough entropy to continue. */ -#define APR_STATUS_IS_ENOTENOUGHENTROPY(s) ((s) == APR_ENOTENOUGHENTROPY) - -/** @} */ - -/** - * @addtogroup APR_Error - * @{ - */ -/** @see APR_STATUS_IS_INCHILD */ -#define APR_INCHILD (APR_OS_START_STATUS + 1) -/** @see APR_STATUS_IS_INPARENT */ -#define APR_INPARENT (APR_OS_START_STATUS + 2) -/** @see APR_STATUS_IS_DETACH */ -#define APR_DETACH (APR_OS_START_STATUS + 3) -/** @see APR_STATUS_IS_NOTDETACH */ -#define APR_NOTDETACH (APR_OS_START_STATUS + 4) -/** @see APR_STATUS_IS_CHILD_DONE */ -#define APR_CHILD_DONE (APR_OS_START_STATUS + 5) -/** @see APR_STATUS_IS_CHILD_NOTDONE */ -#define APR_CHILD_NOTDONE (APR_OS_START_STATUS + 6) -/** @see APR_STATUS_IS_TIMEUP */ -#define APR_TIMEUP (APR_OS_START_STATUS + 7) -/** @see APR_STATUS_IS_INCOMPLETE */ -#define APR_INCOMPLETE (APR_OS_START_STATUS + 8) -/* empty slot: +9 */ -/* empty slot: +10 */ -/* empty slot: +11 */ -/** @see APR_STATUS_IS_BADCH */ -#define APR_BADCH (APR_OS_START_STATUS + 12) -/** @see APR_STATUS_IS_BADARG */ -#define APR_BADARG (APR_OS_START_STATUS + 13) -/** @see APR_STATUS_IS_EOF */ -#define APR_EOF (APR_OS_START_STATUS + 14) -/** @see APR_STATUS_IS_NOTFOUND */ -#define APR_NOTFOUND (APR_OS_START_STATUS + 15) -/* empty slot: +16 */ -/* empty slot: +17 */ -/* empty slot: +18 */ -/** @see APR_STATUS_IS_ANONYMOUS */ -#define APR_ANONYMOUS (APR_OS_START_STATUS + 19) -/** @see APR_STATUS_IS_FILEBASED */ -#define APR_FILEBASED (APR_OS_START_STATUS + 20) -/** @see APR_STATUS_IS_KEYBASED */ -#define APR_KEYBASED (APR_OS_START_STATUS + 21) -/** @see APR_STATUS_IS_EINIT */ -#define APR_EINIT (APR_OS_START_STATUS + 22) -/** @see APR_STATUS_IS_ENOTIMPL */ -#define APR_ENOTIMPL (APR_OS_START_STATUS + 23) -/** @see APR_STATUS_IS_EMISMATCH */ -#define APR_EMISMATCH (APR_OS_START_STATUS + 24) -/** @see APR_STATUS_IS_EBUSY */ -#define APR_EBUSY (APR_OS_START_STATUS + 25) -/** @} */ - -/** - * @addtogroup APR_STATUS_IS - * @{ - */ -/** - * Program is currently executing in the child - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code */ -#define APR_STATUS_IS_INCHILD(s) ((s) == APR_INCHILD) -/** - * Program is currently executing in the parent - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_INPARENT(s) ((s) == APR_INPARENT) -/** - * The thread is detached - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_DETACH(s) ((s) == APR_DETACH) -/** - * The thread is not detached - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_NOTDETACH(s) ((s) == APR_NOTDETACH) -/** - * The child has finished executing - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_CHILD_DONE(s) ((s) == APR_CHILD_DONE) -/** - * The child has not finished executing - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_CHILD_NOTDONE(s) ((s) == APR_CHILD_NOTDONE) -/** - * The operation did not finish before the timeout - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP) -/** - * The operation was incomplete although some processing was performed - * and the results are partially valid. - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_INCOMPLETE(s) ((s) == APR_INCOMPLETE) -/* empty slot: +9 */ -/* empty slot: +10 */ -/* empty slot: +11 */ -/** - * Getopt found an option not in the option string - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_BADCH(s) ((s) == APR_BADCH) -/** - * Getopt found an option not in the option string and an argument was - * specified in the option string - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_BADARG(s) ((s) == APR_BADARG) -/** - * APR has encountered the end of the file - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EOF(s) ((s) == APR_EOF) -/** - * APR was unable to find the socket in the poll structure - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_NOTFOUND(s) ((s) == APR_NOTFOUND) -/* empty slot: +16 */ -/* empty slot: +17 */ -/* empty slot: +18 */ -/** - * APR is using anonymous shared memory - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ANONYMOUS(s) ((s) == APR_ANONYMOUS) -/** - * APR is using a file name as the key to the shared memory - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_FILEBASED(s) ((s) == APR_FILEBASED) -/** - * APR is using a shared key as the key to the shared memory - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_KEYBASED(s) ((s) == APR_KEYBASED) -/** - * Ininitalizer value. If no option has been found, but - * the status variable requires a value, this should be used - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EINIT(s) ((s) == APR_EINIT) -/** - * The APR function has not been implemented on this - * platform, either because nobody has gotten to it yet, - * or the function is impossible on this platform. - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_ENOTIMPL(s) ((s) == APR_ENOTIMPL) -/** - * Two passwords do not match. - * @warning - * always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EMISMATCH(s) ((s) == APR_EMISMATCH) -/** - * The given lock was busy - * @warning always use this test, as platform-specific variances may meet this - * more than one error code - */ -#define APR_STATUS_IS_EBUSY(s) ((s) == APR_EBUSY) - -/** @} */ - -/** - * @addtogroup APR_Error APR Error Values - * @{ - */ -/* APR CANONICAL ERROR VALUES */ -/** @see APR_STATUS_IS_EACCES */ -#ifdef EACCES -#define APR_EACCES EACCES -#else -#define APR_EACCES (APR_OS_START_CANONERR + 1) -#endif - -/** @see APR_STATUS_IS_EXIST */ -#ifdef EEXIST -#define APR_EEXIST EEXIST -#else -#define APR_EEXIST (APR_OS_START_CANONERR + 2) -#endif - -/** @see APR_STATUS_IS_ENAMETOOLONG */ -#ifdef ENAMETOOLONG -#define APR_ENAMETOOLONG ENAMETOOLONG -#else -#define APR_ENAMETOOLONG (APR_OS_START_CANONERR + 3) -#endif - -/** @see APR_STATUS_IS_ENOENT */ -#ifdef ENOENT -#define APR_ENOENT ENOENT -#else -#define APR_ENOENT (APR_OS_START_CANONERR + 4) -#endif - -/** @see APR_STATUS_IS_ENOTDIR */ -#ifdef ENOTDIR -#define APR_ENOTDIR ENOTDIR -#else -#define APR_ENOTDIR (APR_OS_START_CANONERR + 5) -#endif - -/** @see APR_STATUS_IS_ENOSPC */ -#ifdef ENOSPC -#define APR_ENOSPC ENOSPC -#else -#define APR_ENOSPC (APR_OS_START_CANONERR + 6) -#endif - -/** @see APR_STATUS_IS_ENOMEM */ -#ifdef ENOMEM -#define APR_ENOMEM ENOMEM -#else -#define APR_ENOMEM (APR_OS_START_CANONERR + 7) -#endif - -/** @see APR_STATUS_IS_EMFILE */ -#ifdef EMFILE -#define APR_EMFILE EMFILE -#else -#define APR_EMFILE (APR_OS_START_CANONERR + 8) -#endif - -/** @see APR_STATUS_IS_ENFILE */ -#ifdef ENFILE -#define APR_ENFILE ENFILE -#else -#define APR_ENFILE (APR_OS_START_CANONERR + 9) -#endif - -/** @see APR_STATUS_IS_EBADF */ -#ifdef EBADF -#define APR_EBADF EBADF -#else -#define APR_EBADF (APR_OS_START_CANONERR + 10) -#endif - -/** @see APR_STATUS_IS_EINVAL */ -#ifdef EINVAL -#define APR_EINVAL EINVAL -#else -#define APR_EINVAL (APR_OS_START_CANONERR + 11) -#endif - -/** @see APR_STATUS_IS_ESPIPE */ -#ifdef ESPIPE -#define APR_ESPIPE ESPIPE -#else -#define APR_ESPIPE (APR_OS_START_CANONERR + 12) -#endif - -/** - * @see APR_STATUS_IS_EAGAIN - * @warning use APR_STATUS_IS_EAGAIN instead of just testing this value - */ -#ifdef EAGAIN -#define APR_EAGAIN EAGAIN -#elif defined(EWOULDBLOCK) -#define APR_EAGAIN EWOULDBLOCK -#else -#define APR_EAGAIN (APR_OS_START_CANONERR + 13) -#endif - -/** @see APR_STATUS_IS_EINTR */ -#ifdef EINTR -#define APR_EINTR EINTR -#else -#define APR_EINTR (APR_OS_START_CANONERR + 14) -#endif - -/** @see APR_STATUS_IS_ENOTSOCK */ -#ifdef ENOTSOCK -#define APR_ENOTSOCK ENOTSOCK -#else -#define APR_ENOTSOCK (APR_OS_START_CANONERR + 15) -#endif - -/** @see APR_STATUS_IS_ECONNREFUSED */ -#ifdef ECONNREFUSED -#define APR_ECONNREFUSED ECONNREFUSED -#else -#define APR_ECONNREFUSED (APR_OS_START_CANONERR + 16) -#endif - -/** @see APR_STATUS_IS_EINPROGRESS */ -#ifdef EINPROGRESS -#define APR_EINPROGRESS EINPROGRESS -#else -#define APR_EINPROGRESS (APR_OS_START_CANONERR + 17) -#endif - -/** - * @see APR_STATUS_IS_ECONNABORTED - * @warning use APR_STATUS_IS_ECONNABORTED instead of just testing this value - */ - -#ifdef ECONNABORTED -#define APR_ECONNABORTED ECONNABORTED -#else -#define APR_ECONNABORTED (APR_OS_START_CANONERR + 18) -#endif - -/** @see APR_STATUS_IS_ECONNRESET */ -#ifdef ECONNRESET -#define APR_ECONNRESET ECONNRESET -#else -#define APR_ECONNRESET (APR_OS_START_CANONERR + 19) -#endif - -/** @see APR_STATUS_IS_ETIMEDOUT - * @deprecated */ -#ifdef ETIMEDOUT -#define APR_ETIMEDOUT ETIMEDOUT -#else -#define APR_ETIMEDOUT (APR_OS_START_CANONERR + 20) -#endif - -/** @see APR_STATUS_IS_EHOSTUNREACH */ -#ifdef EHOSTUNREACH -#define APR_EHOSTUNREACH EHOSTUNREACH -#else -#define APR_EHOSTUNREACH (APR_OS_START_CANONERR + 21) -#endif - -/** @see APR_STATUS_IS_ENETUNREACH */ -#ifdef ENETUNREACH -#define APR_ENETUNREACH ENETUNREACH -#else -#define APR_ENETUNREACH (APR_OS_START_CANONERR + 22) -#endif - -/** @see APR_STATUS_IS_EFTYPE */ -#ifdef EFTYPE -#define APR_EFTYPE EFTYPE -#else -#define APR_EFTYPE (APR_OS_START_CANONERR + 23) -#endif - -/** @see APR_STATUS_IS_EPIPE */ -#ifdef EPIPE -#define APR_EPIPE EPIPE -#else -#define APR_EPIPE (APR_OS_START_CANONERR + 24) -#endif - -/** @see APR_STATUS_IS_EXDEV */ -#ifdef EXDEV -#define APR_EXDEV EXDEV -#else -#define APR_EXDEV (APR_OS_START_CANONERR + 25) -#endif - -/** @see APR_STATUS_IS_ENOTEMPTY */ -#ifdef ENOTEMPTY -#define APR_ENOTEMPTY ENOTEMPTY -#else -#define APR_ENOTEMPTY (APR_OS_START_CANONERR + 26) -#endif - -/** @} */ - -#if defined(OS2) && !defined(DOXYGEN) - -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -#define INCL_DOSERRORS -#define INCL_DOS - -/* Leave these undefined. - * OS2 doesn't rely on the errno concept. - * The API calls always return a result codes which - * should be filtered through APR_FROM_OS_ERROR(). - * - * #define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) - * #define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) - */ - -/* A special case, only socket calls require this; - */ -#define apr_get_netos_error() (APR_FROM_OS_ERROR(errno)) -#define apr_set_netos_error(e) (errno = APR_TO_OS_ERROR(e)) - -/* And this needs to be greped away for good: - */ -#define APR_OS2_STATUS(e) (APR_FROM_OS_ERROR(e)) - -/* These can't sit in a private header, so in spite of the extra size, - * they need to be made available here. - */ -#define SOCBASEERR 10000 -#define SOCEPERM (SOCBASEERR+1) /* Not owner */ -#define SOCESRCH (SOCBASEERR+3) /* No such process */ -#define SOCEINTR (SOCBASEERR+4) /* Interrupted system call */ -#define SOCENXIO (SOCBASEERR+6) /* No such device or address */ -#define SOCEBADF (SOCBASEERR+9) /* Bad file number */ -#define SOCEACCES (SOCBASEERR+13) /* Permission denied */ -#define SOCEFAULT (SOCBASEERR+14) /* Bad address */ -#define SOCEINVAL (SOCBASEERR+22) /* Invalid argument */ -#define SOCEMFILE (SOCBASEERR+24) /* Too many open files */ -#define SOCEPIPE (SOCBASEERR+32) /* Broken pipe */ -#define SOCEOS2ERR (SOCBASEERR+100) /* OS/2 Error */ -#define SOCEWOULDBLOCK (SOCBASEERR+35) /* Operation would block */ -#define SOCEINPROGRESS (SOCBASEERR+36) /* Operation now in progress */ -#define SOCEALREADY (SOCBASEERR+37) /* Operation already in progress */ -#define SOCENOTSOCK (SOCBASEERR+38) /* Socket operation on non-socket */ -#define SOCEDESTADDRREQ (SOCBASEERR+39) /* Destination address required */ -#define SOCEMSGSIZE (SOCBASEERR+40) /* Message too long */ -#define SOCEPROTOTYPE (SOCBASEERR+41) /* Protocol wrong type for socket */ -#define SOCENOPROTOOPT (SOCBASEERR+42) /* Protocol not available */ -#define SOCEPROTONOSUPPORT (SOCBASEERR+43) /* Protocol not supported */ -#define SOCESOCKTNOSUPPORT (SOCBASEERR+44) /* Socket type not supported */ -#define SOCEOPNOTSUPP (SOCBASEERR+45) /* Operation not supported on socket */ -#define SOCEPFNOSUPPORT (SOCBASEERR+46) /* Protocol family not supported */ -#define SOCEAFNOSUPPORT (SOCBASEERR+47) /* Address family not supported by protocol family */ -#define SOCEADDRINUSE (SOCBASEERR+48) /* Address already in use */ -#define SOCEADDRNOTAVAIL (SOCBASEERR+49) /* Can't assign requested address */ -#define SOCENETDOWN (SOCBASEERR+50) /* Network is down */ -#define SOCENETUNREACH (SOCBASEERR+51) /* Network is unreachable */ -#define SOCENETRESET (SOCBASEERR+52) /* Network dropped connection on reset */ -#define SOCECONNABORTED (SOCBASEERR+53) /* Software caused connection abort */ -#define SOCECONNRESET (SOCBASEERR+54) /* Connection reset by peer */ -#define SOCENOBUFS (SOCBASEERR+55) /* No buffer space available */ -#define SOCEISCONN (SOCBASEERR+56) /* Socket is already connected */ -#define SOCENOTCONN (SOCBASEERR+57) /* Socket is not connected */ -#define SOCESHUTDOWN (SOCBASEERR+58) /* Can't send after socket shutdown */ -#define SOCETOOMANYREFS (SOCBASEERR+59) /* Too many references: can't splice */ -#define SOCETIMEDOUT (SOCBASEERR+60) /* Connection timed out */ -#define SOCECONNREFUSED (SOCBASEERR+61) /* Connection refused */ -#define SOCELOOP (SOCBASEERR+62) /* Too many levels of symbolic links */ -#define SOCENAMETOOLONG (SOCBASEERR+63) /* File name too long */ -#define SOCEHOSTDOWN (SOCBASEERR+64) /* Host is down */ -#define SOCEHOSTUNREACH (SOCBASEERR+65) /* No route to host */ -#define SOCENOTEMPTY (SOCBASEERR+66) /* Directory not empty */ - -/* APR CANONICAL ERROR TESTS */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ - || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ - || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ - || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ - || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ - || (s) == APR_OS_START_SYSERR + SOCENAMETOOLONG) -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES \ - || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED) -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ - || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ - || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE) -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION) -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ - || (s) == APR_OS_START_SYSERR + SOCEWOULDBLOCK \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION) -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ - || (s) == APR_OS_START_SYSERR + SOCEINTR) -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ - || (s) == APR_OS_START_SYSERR + SOCENOTSOCK) -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ - || (s) == APR_OS_START_SYSERR + SOCECONNREFUSED) -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ - || (s) == APR_OS_START_SYSERR + SOCEINPROGRESS) -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == APR_OS_START_SYSERR + SOCECONNABORTED) -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ - || (s) == APR_OS_START_SYSERR + SOCECONNRESET) -/* XXX deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) -#undef APR_STATUS_IS_TIMEUP -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ - || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ - || (s) == APR_OS_START_SYSERR + SOCEHOSTUNREACH) -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ - || (s) == APR_OS_START_SYSERR + SOCENETUNREACH) -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE \ - || (s) == APR_OS_START_SYSERR + SOCEPIPE) -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ - || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) - -/* - Sorry, too tired to wrap this up for OS2... feel free to - fit the following into their best matches. - - { ERROR_NO_SIGNAL_SENT, ESRCH }, - { SOCEALREADY, EALREADY }, - { SOCEDESTADDRREQ, EDESTADDRREQ }, - { SOCEMSGSIZE, EMSGSIZE }, - { SOCEPROTOTYPE, EPROTOTYPE }, - { SOCENOPROTOOPT, ENOPROTOOPT }, - { SOCEPROTONOSUPPORT, EPROTONOSUPPORT }, - { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT }, - { SOCEOPNOTSUPP, EOPNOTSUPP }, - { SOCEPFNOSUPPORT, EPFNOSUPPORT }, - { SOCEAFNOSUPPORT, EAFNOSUPPORT }, - { SOCEADDRINUSE, EADDRINUSE }, - { SOCEADDRNOTAVAIL, EADDRNOTAVAIL }, - { SOCENETDOWN, ENETDOWN }, - { SOCENETRESET, ENETRESET }, - { SOCENOBUFS, ENOBUFS }, - { SOCEISCONN, EISCONN }, - { SOCENOTCONN, ENOTCONN }, - { SOCESHUTDOWN, ESHUTDOWN }, - { SOCETOOMANYREFS, ETOOMANYREFS }, - { SOCELOOP, ELOOP }, - { SOCEHOSTDOWN, EHOSTDOWN }, - { SOCENOTEMPTY, ENOTEMPTY }, - { SOCEPIPE, EPIPE } -*/ - -#elif defined(WIN32) && !defined(DOXYGEN) /* !defined(OS2) */ - -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -#define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) -#define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) - -/* A special case, only socket calls require this: - */ -#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) -#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) - -/* APR CANONICAL ERROR TESTS */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ - || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ - || (s) == APR_OS_START_SYSERR + ERROR_CANNOT_MAKE \ - || (s) == APR_OS_START_SYSERR + ERROR_CURRENT_DIRECTORY \ - || (s) == APR_OS_START_SYSERR + ERROR_DRIVE_LOCKED \ - || (s) == APR_OS_START_SYSERR + ERROR_FAIL_I24 \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_FAILED \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_LOCKED \ - || (s) == APR_OS_START_SYSERR + ERROR_NETWORK_ACCESS_DENIED \ - || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ - || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS) -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ - || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ - || (s) == APR_OS_START_SYSERR + WSAENAMETOOLONG) -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES) -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR \ - || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_NETPATH \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_NET_NAME \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_PATHNAME \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DRIVE) -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ - || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM \ - || (s) == APR_OS_START_SYSERR + ERROR_ARENA_TRASHED \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_MEMORY \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_BLOCK \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_QUOTA \ - || (s) == APR_OS_START_SYSERR + ERROR_OUTOFMEMORY) -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ - || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_TARGET_HANDLE) -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_ACCESS \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DATA \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ - || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_SEEK_ON_DEVICE \ - || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ - || (s) == APR_OS_START_SYSERR + ERROR_NO_PROC_SLOTS \ - || (s) == APR_OS_START_SYSERR + ERROR_NESTING_NOT_ALLOWED \ - || (s) == APR_OS_START_SYSERR + ERROR_MAX_THRDS_REACHED \ - || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ - || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ - || (s) == APR_OS_START_SYSERR + WSAEINTR) -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ - || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ - || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ - || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ - || (s) == APR_OS_START_SYSERR + ERROR_NETNAME_DELETED \ - || (s) == APR_OS_START_SYSERR + WSAECONNRESET) -/* XXX deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#undef APR_STATUS_IS_TIMEUP -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE \ - || (s) == APR_OS_START_SYSERR + ERROR_EXE_MACHINE_TYPE_MISMATCH \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DLL \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_MODULETYPE \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_EXE_FORMAT \ - || (s) == APR_OS_START_SYSERR + ERROR_INVALID_EXE_SIGNATURE \ - || (s) == APR_OS_START_SYSERR + ERROR_FILE_CORRUPT \ - || (s) == APR_OS_START_SYSERR + ERROR_BAD_FORMAT) -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ - || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE) -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ - || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ - || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY) - -#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */ - -#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) -#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) - -#define apr_get_os_error() (errno) -#define apr_set_os_error(e) (errno = (e)) - -/* A special case, only socket calls require this: */ -#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) -#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) - -/* APR CANONICAL ERROR TESTS */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) - -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == EWOULDBLOCK \ - || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ - || (s) == APR_OS_START_SYSERR + WSAEINTR) -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ - || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ - || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ - || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ - || (s) == APR_OS_START_SYSERR + WSAECONNRESET) -/* XXX deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#undef APR_STATUS_IS_TIMEUP -#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ - || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ - || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ - || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) -#define APR_STATUS_IS_ENETDOWN(s) ((s) == APR_OS_START_SYSERR + WSAENETDOWN) -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY) - -#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ - -/* - * os error codes are clib error codes - */ -#define APR_FROM_OS_ERROR(e) (e) -#define APR_TO_OS_ERROR(e) (e) - -#define apr_get_os_error() (errno) -#define apr_set_os_error(e) (errno = (e)) - -/* A special case, only socket calls require this: - */ -#define apr_get_netos_error() (errno) -#define apr_set_netos_error(e) (errno = (e)) - -/** - * @addtogroup APR_STATUS_IS - * @{ - */ - -/** permission denied */ -#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) -/** file exists */ -#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) -/** path name is too long */ -#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) -/** - * no such file or directory - * @remark - * EMVSCATLG can be returned by the automounter on z/OS for - * paths which do not exist. - */ -#ifdef EMVSCATLG -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ - || (s) == EMVSCATLG) -#else -#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) -#endif -/** not a directory */ -#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) -/** no space left on device */ -#ifdef EDQUOT -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ - || (s) == EDQUOT) -#else -#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) -#endif -/** not enough memory */ -#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) -/** too many open files */ -#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) -/** file table overflow */ -#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) -/** bad file # */ -#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) -/** invalid argument */ -#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) -/** illegal seek */ -#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) - -/** operation would block */ -#if !defined(EWOULDBLOCK) || !defined(EAGAIN) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) -#elif (EWOULDBLOCK == EAGAIN) -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) -#else -#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ - || (s) == EWOULDBLOCK) -#endif - -/** interrupted system call */ -#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR) -/** socket operation on a non-socket */ -#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK) -/** Connection Refused */ -#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED) -/** operation now in progress */ -#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS) - -/** - * Software caused connection abort - * @remark - * EPROTO on certain older kernels really means ECONNABORTED, so we need to - * ignore it for them. See discussion in new-httpd archives nh.9701 & nh.9603 - * - * There is potentially a bug in Solaris 2.x x<6, and other boxes that - * implement tcp sockets in userland (i.e. on top of STREAMS). On these - * systems, EPROTO can actually result in a fatal loop. See PR#981 for - * example. It's hard to handle both uses of EPROTO. - */ -#ifdef EPROTO -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ - || (s) == EPROTO) -#else -#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED) -#endif - -/** Connection Reset by peer */ -#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET) -/** Operation timed out - * @deprecated */ -#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT) -/** no route to host */ -#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH) -/** network is unreachable */ -#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH) -/** inappropiate file type or format */ -#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) -/** broken pipe */ -#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) -/** cross device link */ -#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) -/** Directory Not Empty */ -#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY || \ - (s) == APR_EEXIST) -/** @} */ - -#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* ! APR_ERRNO_H */ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <sys/errno.h> - - -/* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)errno.h 8.5 (Berkeley) 1/21/94 - */ - -#ifndef _SYS_ERRNO_H_ -#define _SYS_ERRNO_H_ - -#include <sys/cdefs.h> -__BEGIN_DECLS -extern int * __error(void); -#define errno (*__error()) -__END_DECLS - -/* - * Error codes - */ - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* Input/output error */ -#define ENXIO 6 /* Device not configured */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file descriptor */ -#define ECHILD 10 /* No child processes */ -#define EDEADLK 11 /* Resource deadlock avoided */ - /* 11 was EAGAIN */ -#define ENOMEM 12 /* Cannot allocate memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define ENOTBLK 15 /* Block device required */ -#endif -#define EBUSY 16 /* Device / Resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* Operation not supported by device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* Too many open files in system */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Inappropriate ioctl for device */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ - -/* math software */ -#define EDOM 33 /* Numerical argument out of domain */ -#define ERANGE 34 /* Result too large */ - -/* non-blocking and interrupt i/o */ -#define EAGAIN 35 /* Resource temporarily unavailable */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define EINPROGRESS 36 /* Operation now in progress */ -#define EALREADY 37 /* Operation already in progress */ - -/* ipc/network software -- argument errors */ -#define ENOTSOCK 38 /* Socket operation on non-socket */ -#define EDESTADDRREQ 39 /* Destination address required */ -#define EMSGSIZE 40 /* Message too long */ -#define EPROTOTYPE 41 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 42 /* Protocol not available */ -#define EPROTONOSUPPORT 43 /* Protocol not supported */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ -#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ -#define ENOTSUP 45 /* Operation not supported */ -#if !__DARWIN_UNIX03 && !defined(KERNEL) -/* - * This is the same for binary and source copmpatability, unless compiling - * the kernel itself, or compiling __DARWIN_UNIX03; if compiling for the - * kernel, the correct value will be returned. If compiling non-POSIX - * source, the kernel return value will be converted by a stub in libc, and - * if compiling source with __DARWIN_UNIX03, the conversion in libc is not - * done, and the caller gets the expected (discrete) value. - */ -#define EOPNOTSUPP ENOTSUP /* Operation not supported on socket */ -#endif /* !__DARWIN_UNIX03 && !KERNEL */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EPFNOSUPPORT 46 /* Protocol family not supported */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ -#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ -#define EADDRINUSE 48 /* Address already in use */ -#define EADDRNOTAVAIL 49 /* Can't assign requested address */ - -/* ipc/network software -- operational errors */ -#define ENETDOWN 50 /* Network is down */ -#define ENETUNREACH 51 /* Network is unreachable */ -#define ENETRESET 52 /* Network dropped connection on reset */ -#define ECONNABORTED 53 /* Software caused connection abort */ -#define ECONNRESET 54 /* Connection reset by peer */ -#define ENOBUFS 55 /* No buffer space available */ -#define EISCONN 56 /* Socket is already connected */ -#define ENOTCONN 57 /* Socket is not connected */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define ESHUTDOWN 58 /* Can't send after socket shutdown */ -#define ETOOMANYREFS 59 /* Too many references: can't splice */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ -#define ETIMEDOUT 60 /* Operation timed out */ -#define ECONNREFUSED 61 /* Connection refused */ - -#define ELOOP 62 /* Too many levels of symbolic links */ -#define ENAMETOOLONG 63 /* File name too long */ - -/* should be rearranged */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EHOSTDOWN 64 /* Host is down */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ -#define EHOSTUNREACH 65 /* No route to host */ -#define ENOTEMPTY 66 /* Directory not empty */ - -/* quotas & mush */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EPROCLIM 67 /* Too many processes */ -#define EUSERS 68 /* Too many users */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ -#define EDQUOT 69 /* Disc quota exceeded */ - -/* Network File System */ -#define ESTALE 70 /* Stale NFS file handle */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EREMOTE 71 /* Too many levels of remote in path */ -#define EBADRPC 72 /* RPC struct is bad */ -#define ERPCMISMATCH 73 /* RPC version wrong */ -#define EPROGUNAVAIL 74 /* RPC prog. not avail */ -#define EPROGMISMATCH 75 /* Program version wrong */ -#define EPROCUNAVAIL 76 /* Bad procedure for program */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -#define ENOLCK 77 /* No locks available */ -#define ENOSYS 78 /* Function not implemented */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EFTYPE 79 /* Inappropriate file type or format */ -#define EAUTH 80 /* Authentication error */ -#define ENEEDAUTH 81 /* Need authenticator */ - -/* Intelligent device errors */ -#define EPWROFF 82 /* Device power is off */ -#define EDEVERR 83 /* Device error, e.g. paper out */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -#define EOVERFLOW 84 /* Value too large to be stored in data type */ - -/* Program loading errors */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EBADEXEC 85 /* Bad executable */ -#define EBADARCH 86 /* Bad CPU type in executable */ -#define ESHLIBVERS 87 /* Shared library version mismatch */ -#define EBADMACHO 88 /* Malformed Macho file */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -#define ECANCELED 89 /* Operation canceled */ - -#define EIDRM 90 /* Identifier removed */ -#define ENOMSG 91 /* No message of desired type */ -#define EILSEQ 92 /* Illegal byte sequence */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define ENOATTR 93 /* Attribute not found */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -#define EBADMSG 94 /* Bad message */ -#define EMULTIHOP 95 /* Reserved */ -#define ENODATA 96 /* No message available on STREAM */ -#define ENOLINK 97 /* Reserved */ -#define ENOSR 98 /* No STREAM resources */ -#define ENOSTR 99 /* Not a STREAM */ -#define EPROTO 100 /* Protocol error */ -#define ETIME 101 /* STREAM ioctl timeout */ - -#if __DARWIN_UNIX03 || defined(KERNEL) -/* This value is only discrete when compiling __DARWIN_UNIX03, or KERNEL */ -#define EOPNOTSUPP 102 /* Operation not supported on socket */ -#endif /* __DARWIN_UNIX03 || KERNEL */ - -#define ENOPOLICY 103 /* No such policy registered */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define ELAST 103 /* Must be equal largest errno */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -#endif /* _SYS_ERRNO_H_ */ diff --git a/doc/errno.list.solaris.txt b/doc/errno.list.solaris.txt deleted file mode 100644 index 23601e9d374..00000000000 --- a/doc/errno.list.solaris.txt +++ /dev/null @@ -1,206 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2000 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ - -/* - * University Copyright- Copyright (c) 1982, 1986, 1988 - * The Regents of the University of California - * All Rights Reserved - * - * University Acknowledgment- Portions of this document are derived from - * software developed by the University of California, Berkeley, and its - * contributors. - */ - -#ifndef _SYS_ERRNO_H -#define _SYS_ERRNO_H - -#pragma ident "@(#)errno.h 1.22 05/06/08 SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Error codes - */ - -#define EPERM 1 /* Not super-user */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No children */ -#define EAGAIN 11 /* Resource temporarily unavailable */ -#define ENOMEM 12 /* Not enough core */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Mount device busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Inappropriate ioctl for device */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math arg out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define ENOMSG 35 /* No message of desired type */ -#define EIDRM 36 /* Identifier removed */ -#define ECHRNG 37 /* Channel number out of range */ -#define EL2NSYNC 38 /* Level 2 not synchronized */ -#define EL3HLT 39 /* Level 3 halted */ -#define EL3RST 40 /* Level 3 reset */ -#define ELNRNG 41 /* Link number out of range */ -#define EUNATCH 42 /* Protocol driver not attached */ -#define ENOCSI 43 /* No CSI structure available */ -#define EL2HLT 44 /* Level 2 halted */ -#define EDEADLK 45 /* Deadlock condition. */ -#define ENOLCK 46 /* No record locks available. */ -#define ECANCELED 47 /* Operation canceled */ -#define ENOTSUP 48 /* Operation not supported */ - -/* Filesystem Quotas */ -#define EDQUOT 49 /* Disc quota exceeded */ - -/* Convergent Error Returns */ -#define EBADE 50 /* invalid exchange */ -#define EBADR 51 /* invalid request descriptor */ -#define EXFULL 52 /* exchange full */ -#define ENOANO 53 /* no anode */ -#define EBADRQC 54 /* invalid request code */ -#define EBADSLT 55 /* invalid slot */ -#define EDEADLOCK 56 /* file locking deadlock error */ - -#define EBFONT 57 /* bad font file fmt */ - -/* Interprocess Robust Locks */ -#define EOWNERDEAD 58 /* process died with the lock */ -#define ENOTRECOVERABLE 59 /* lock is not recoverable */ - -/* stream problems */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* no data (for no delay io) */ -#define ETIME 62 /* timer expired */ -#define ENOSR 63 /* out of streams resources */ - -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* The object is remote */ -#define ENOLINK 67 /* the link has been severed */ -#define EADV 68 /* advertise error */ -#define ESRMNT 69 /* srmount error */ - -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ - -/* Interprocess Robust Locks */ -#define ELOCKUNMAPPED 72 /* locked lock was unmapped */ - -#define ENOTACTIVE 73 /* Facility is not active */ -#define EMULTIHOP 74 /* multihop attempted */ -#define EBADMSG 77 /* trying to read unreadable message */ -#define ENAMETOOLONG 78 /* path name is too long */ -#define EOVERFLOW 79 /* value too large to be stored in data type */ -#define ENOTUNIQ 80 /* given log. name not unique */ -#define EBADFD 81 /* f.d. invalid for this operation */ -#define EREMCHG 82 /* Remote address changed */ - -/* shared library problems */ -#define ELIBACC 83 /* Can't access a needed shared lib. */ -#define ELIBBAD 84 /* Accessing a corrupted shared lib. */ -#define ELIBSCN 85 /* .lib section in a.out corrupted. */ -#define ELIBMAX 86 /* Attempting to link in too many libs. */ -#define ELIBEXEC 87 /* Attempting to exec a shared library. */ -#define EILSEQ 88 /* Illegal byte sequence. */ -#define ENOSYS 89 /* Unsupported file system operation */ -#define ELOOP 90 /* Symbolic link loop */ -#define ERESTART 91 /* Restartable system call */ -#define ESTRPIPE 92 /* if pipe/FIFO, don't sleep in stream head */ -#define ENOTEMPTY 93 /* directory not empty */ -#define EUSERS 94 /* Too many users (for UFS) */ - -/* BSD Networking Software */ - /* argument errors */ -#define ENOTSOCK 95 /* Socket operation on non-socket */ -#define EDESTADDRREQ 96 /* Destination address required */ -#define EMSGSIZE 97 /* Message too long */ -#define EPROTOTYPE 98 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 99 /* Protocol not available */ -#define EPROTONOSUPPORT 120 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 121 /* Socket type not supported */ -#define EOPNOTSUPP 122 /* Operation not supported on socket */ -#define EPFNOSUPPORT 123 /* Protocol family not supported */ -#define EAFNOSUPPORT 124 /* Address family not supported by */ - /* protocol family */ -#define EADDRINUSE 125 /* Address already in use */ -#define EADDRNOTAVAIL 126 /* Can't assign requested address */ - /* operational errors */ -#define ENETDOWN 127 /* Network is down */ -#define ENETUNREACH 128 /* Network is unreachable */ -#define ENETRESET 129 /* Network dropped connection because */ - /* of reset */ -#define ECONNABORTED 130 /* Software caused connection abort */ -#define ECONNRESET 131 /* Connection reset by peer */ -#define ENOBUFS 132 /* No buffer space available */ -#define EISCONN 133 /* Socket is already connected */ -#define ENOTCONN 134 /* Socket is not connected */ -/* XENIX has 135 - 142 */ -#define ESHUTDOWN 143 /* Can't send after socket shutdown */ -#define ETOOMANYREFS 144 /* Too many references: can't splice */ -#define ETIMEDOUT 145 /* Connection timed out */ -#define ECONNREFUSED 146 /* Connection refused */ -#define EHOSTDOWN 147 /* Host is down */ -#define EHOSTUNREACH 148 /* No route to host */ -#define EWOULDBLOCK EAGAIN -#define EALREADY 149 /* operation already in progress */ -#define EINPROGRESS 150 /* operation now in progress */ - -/* SUN Network File System */ -#define ESTALE 151 /* Stale NFS file handle */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_ERRNO_H */ diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am deleted file mode 100644 index b4c93f4c90b..00000000000 --- a/doc/examples/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -EXTRA = README unify.vol replicate.vol stripe.vol protocol-client.vol protocol-server.vol posix-locks.vol trash.vol write-behind.vol io-threads.vol io-cache.vol read-ahead.vol filter.vol trace.vol -EXTRA_DIST = $(EXTRA) - -docdir = $(datadir)/doc/$(PACKAGE_NAME) -Examplesdir = $(docdir)/examples -Examples_DATA = $(EXTRA) - -CLEANFILES = diff --git a/doc/examples/README b/doc/examples/README deleted file mode 100644 index 4d472ac086e..00000000000 --- a/doc/examples/README +++ /dev/null @@ -1,13 +0,0 @@ -GlusterFS's translator feature is very flexible and there are quite a lot of ways one -can configure their filesystem to behave like. - -Volume Specification is a way in which GlusterFS understands how it has to work, based -on what is written there. - -Going through the following URLs may give you more idea about all these. - -* http://www.gluster.org/docs/index.php/GlusterFS -* http://www.gluster.org/docs/index.php/GlusterFS_Volume_Specification -* http://www.gluster.org/docs/index.php/GlusterFS_Translators - -Mail us any doubts, suggestions on 'gluster-devel(at)nongnu.org' diff --git a/doc/examples/filter.vol b/doc/examples/filter.vol deleted file mode 100644 index ca5c5983779..00000000000 --- a/doc/examples/filter.vol +++ /dev/null @@ -1,23 +0,0 @@ -volume client - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 192.168.1.10 # IP address of the remote brick - option remote-subvolume brick # name of the remote volume -end-volume - -## In normal clustered storage type, any of the cluster translators can come here. -# -# Definition of other clients -# -# Definition of cluster translator (may be unify, afr, or unify over afr) -# - -### 'Filter' translator is used on client side (or server side according to needs). This traslator makes all the below translators, (or say volumes) as read-only. Hence if one wants a 'read-only' filesystem, using filter as the top most volume will make it really fast as the fops are returned from this level itself. - -volume filter-ro - type features/filter - option root-squashing enable -# option completely-read-only yes -# translate-uid 1-99=0 - subvolumes client -end-volume
\ No newline at end of file diff --git a/doc/examples/io-cache.vol b/doc/examples/io-cache.vol deleted file mode 100644 index 5f3eca4c527..00000000000 --- a/doc/examples/io-cache.vol +++ /dev/null @@ -1,25 +0,0 @@ -volume client - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 192.168.1.10 # IP address of the remote brick - option remote-subvolume brick # name of the remote volume -end-volume - -## In normal clustered storage type, any of the cluster translators can come here. -# -# Definition of other clients -# -# Definition of cluster translator (may be unify, replicate, or unify over replicate) -# - -### 'IO-Cache' translator is best used on client side when a filesystem has file which are not modified frequently but read several times. For example, while compiling a kernel, *.h files are read while compiling every *.c file, in these case, io-cache translator comes very handy, as it keeps the whole file content in the cache, and serves from the cache. -# One can provide the priority of the cache too. - -volume ioc - type performance/io-cache - subvolumes client # In this example it is 'client' you may have to change it according to your spec file. - option page-size 1MB # 128KB is default - option cache-size 64MB # 32MB is default - option force-revalidate-timeout 5 # 1second is default - option priority *.html:2,*:1 # default is *:0 -end-volume diff --git a/doc/examples/io-threads.vol b/doc/examples/io-threads.vol deleted file mode 100644 index 9954724e1fe..00000000000 --- a/doc/examples/io-threads.vol +++ /dev/null @@ -1,21 +0,0 @@ - -volume brick - type storage/posix # POSIX FS translator - option directory /home/export # Export this directory -end-volume - -### 'IO-threads' translator gives a threading behaviour to File I/O calls. All other normal fops are having default behaviour. Loading this on server side helps to reduce the contension of network. (Which is assumed as a GlusterFS hang). -# One can load it in client side to reduce the latency involved in case of a slow network, when loaded below write-behind. -volume iot - type performance/io-threads - subvolumes brick - option thread-count 4 # default value is 1 -end-volume - -volume server - type protocol/server - subvolumes iot brick - option transport-type tcp # For TCP/IP transport - option auth.addr.brick.allow 192.168.* # Allow access to "brick" volume - option auth.addr.iot.allow 192.168.* # Allow access to "p-locks" volume -end-volume diff --git a/doc/examples/posix-locks.vol b/doc/examples/posix-locks.vol deleted file mode 100644 index b9c9e7a6481..00000000000 --- a/doc/examples/posix-locks.vol +++ /dev/null @@ -1,20 +0,0 @@ - -volume brick - type storage/posix # POSIX FS translator - option directory /home/export # Export this directory -end-volume - -### 'Posix-locks' feature should be added on the server side (as posix volume as subvolume) because it contains the actual file. -volume p-locks - type features/posix-locks - subvolumes brick - option mandatory on -end-volume - -volume server - type protocol/server - subvolumes p-locks brick - option transport-type tcp - option auth.addr.brick.allow 192.168.* # Allow access to "brick" volume - option auth.addr.p-locks.allow 192.168.* # Allow access to "p-locks" volume -end-volume diff --git a/doc/examples/protocol-client.vol b/doc/examples/protocol-client.vol deleted file mode 100644 index 43c43e02d54..00000000000 --- a/doc/examples/protocol-client.vol +++ /dev/null @@ -1,17 +0,0 @@ -volume client - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport - option remote-host 192.168.1.10 # IP address of the remote brick -# option transport.socket.remote-port 24016 - -# option transport-type ib-verbs # for Infiniband verbs transport -# option transport.ib-verbs.work-request-send-size 1048576 -# option transport.ib-verbs.work-request-send-count 16 -# option transport.ib-verbs.work-request-recv-size 1048576 -# option transport.ib-verbs.work-request-recv-count 16 -# option transport.ib-verbs.remote-port 24016 - - option remote-subvolume brick # name of the remote volume -# option transport-timeout 30 # default value is 120seconds -end-volume diff --git a/doc/examples/protocol-server.vol b/doc/examples/protocol-server.vol deleted file mode 100644 index e8e4a464383..00000000000 --- a/doc/examples/protocol-server.vol +++ /dev/null @@ -1,25 +0,0 @@ - -### Export volume "brick" with the contents of "/home/export" directory. -volume brick - type storage/posix # POSIX FS translator - option directory /home/export # Export this directory -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport -# option transport.socket.listen-port 24016 - -# option transport-type ib-verbs # For Infiniband Verbs transport -# option transport.ib-verbs.work-request-send-size 131072 -# option transport.ib-verbs.work-request-send-count 64 -# option transport.ib-verbs.work-request-recv-size 131072 -# option transport.ib-verbs.work-request-recv-count 64 -# option transport.ib-verbs.listen-port 24016 - -# option bind-address 192.168.1.10 # Default is to listen on all interfaces -# option client-volume-filename /etc/glusterfs/glusterfs-client.vol - subvolumes brick - option auth.addr.brick.allow 192.168.* # Allow access to "brick" volume -end-volume diff --git a/doc/examples/read-ahead.vol b/doc/examples/read-ahead.vol deleted file mode 100644 index 3ce0d95aca7..00000000000 --- a/doc/examples/read-ahead.vol +++ /dev/null @@ -1,22 +0,0 @@ -volume client - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 192.168.1.10 # IP address of the remote brick - option remote-subvolume brick # name of the remote volume -end-volume - -## In normal clustered storage type, any of the cluster translators can come here. -# -# Definition of other clients -# -# Definition of cluster translator (may be unify, replicate, or unify over replicate) -# - -### 'Read-Ahead' translator is best utilized on client side, as it prefetches the file contents when the first read() call is issued. -volume ra - type performance/read-ahead - subvolumes client # In this example it is 'client' you may have to change it according to your spec file. - option page-size 1MB # default is 256KB - option page-count 4 # default is 2 - option force-atime-update no # defalut is 'no' -end-volume diff --git a/doc/examples/replicate.vol b/doc/examples/replicate.vol deleted file mode 100644 index 333ba7de1aa..00000000000 --- a/doc/examples/replicate.vol +++ /dev/null @@ -1,119 +0,0 @@ -### 'NOTE' -# This file has both server spec and client spec to get an understanding of stripe's spec file. Hence can't be used as it is, as a GlusterFS spec file. -# One need to seperate out server spec and client spec to get it working. - -#========================================================================= - -# **** server1 spec file **** - -### Export volume "brick" with the contents of "/home/export" directory. -volume posix1 - type storage/posix # POSIX FS translator - option directory /home/export1 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick1 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix1 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24016 -# option client-volume-filename /etc/glusterfs/glusterfs-client.vol - subvolumes brick1 - option auth.addr.brick1.allow * # access to "brick" volume -end-volume - - -#========================================================================= - -# **** server2 spec file **** -volume posix2 - type storage/posix # POSIX FS translator - option directory /home/export2 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick2 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix2 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24017 - subvolumes brick2 - option auth.addr.brick2.allow * # Allow access to "brick" volume -end-volume - - -#========================================================================= - -# **** server3 spec file **** - -volume posix3 - type storage/posix # POSIX FS translator - option directory /home/export3 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick3 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix3 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24018 - subvolumes brick3 - option auth.addr.brick3.allow * # access to "brick" volume -end-volume - - -#========================================================================= - -# **** Clustered Client config file **** - -### Add client feature and attach to remote subvolume of server1 -volume client1 - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24016 - option remote-subvolume brick1 # name of the remote volume -end-volume - -### Add client feature and attach to remote subvolume of server2 -volume client2 - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24017 - option remote-subvolume brick2 # name of the remote volume -end-volume - -volume client3 - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24018 - option remote-subvolume brick3 # name of the remote volume -end-volume - -## Add replicate feature. -volume replicate - type cluster/replicate - subvolumes client1 client2 client3 -end-volume - diff --git a/doc/examples/stripe.vol b/doc/examples/stripe.vol deleted file mode 100644 index 6055b66b922..00000000000 --- a/doc/examples/stripe.vol +++ /dev/null @@ -1,121 +0,0 @@ - -### 'NOTE' -# This file has both server spec and client spec to get an understanding of stripe's spec file. Hence can't be used as it is, as a GlusterFS spec file. -# One need to seperate out server spec and client spec to get it working. - -#========================================================================= - -# **** server1 spec file **** - -### Export volume "brick" with the contents of "/home/export" directory. -volume posix1 - type storage/posix # POSIX FS translator - option directory /home/export1 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick1 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix1 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24016 -# option client-volume-filename /etc/glusterfs/glusterfs-client.vol - subvolumes brick1 - option auth.addr.brick1.allow * # access to "brick" volume -end-volume - - -#========================================================================= - -# **** server2 spec file **** -volume posix2 - type storage/posix # POSIX FS translator - option directory /home/export2 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick2 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix2 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24017 - subvolumes brick2 - option auth.addr.brick2.allow * # Allow access to "brick" volume -end-volume - - -#========================================================================= - -# **** server3 spec file **** - -volume posix3 - type storage/posix # POSIX FS translator - option directory /home/export3 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick3 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix3 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24018 - subvolumes brick3 - option auth.addr.brick3.allow * # access to "brick" volume -end-volume - - -#========================================================================= - -# **** Clustered Client config file **** - -### Add client feature and attach to remote subvolume of server1 -volume client1 - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24016 - option remote-subvolume brick1 # name of the remote volume -end-volume - -### Add client feature and attach to remote subvolume of server2 -volume client2 - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24017 - option remote-subvolume brick2 # name of the remote volume -end-volume - -volume client3 - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24018 - option remote-subvolume brick3 # name of the remote volume -end-volume - -## Add Stripe Feature. -volume stripe - type cluster/stripe - subvolumes client1 client2 client3 - option block-size 1MB -end-volume - diff --git a/doc/examples/trace.vol b/doc/examples/trace.vol deleted file mode 100644 index 3f4864db496..00000000000 --- a/doc/examples/trace.vol +++ /dev/null @@ -1,16 +0,0 @@ -volume client - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 192.168.1.10 # IP address of the remote brick - option remote-subvolume brick # name of the remote volume -end-volume - -### 'Trace' translator is a very handy debug tool for GlusterFS, as it can be loaded between any of the two volumes without changing the behaviour of the filesystem. -# On client side it can be the top most volume in spec (like now) to understand what calls are made on FUSE filesystem, when a mounted filesystem is accessed. - -volume trace - type debug/trace - subvolumes client -end-volume - -# 'NOTE:' By loading 'debug/trace' translator, filesystem will be very slow as it logs each and every calls to the log file. diff --git a/doc/examples/trash.vol b/doc/examples/trash.vol deleted file mode 100644 index 16e71be3232..00000000000 --- a/doc/examples/trash.vol +++ /dev/null @@ -1,20 +0,0 @@ - -volume brick - type storage/posix # POSIX FS translator - option directory /home/export # Export this directory -end-volume - -### 'Trash' translator is best used on server side as it just renames the deleted file inside 'trash-dir', and it makes 4 seperate fops for one unlink call. -volume trashcan - type features/trash - subvolumes brick - option trash-dir /.trashcan -end-volume - -volume server - type protocol/server - subvolumes trashcan brick - option transport-type tcp # For TCP/IP transport - option auth.addr.brick.allow 192.168.* # Allow access to "brick" volume - option auth.addr.trashcan.allow 192.168.* # Allow access to "p-locks" volume -end-volume diff --git a/doc/examples/unify.vol b/doc/examples/unify.vol deleted file mode 100644 index 3fb7e832086..00000000000 --- a/doc/examples/unify.vol +++ /dev/null @@ -1,178 +0,0 @@ -### 'NOTE' -# This file has both server spec and client spec to get an understanding of stripe's spec file. Hence can't be used as it is, as a GlusterFS spec file. -# One need to seperate out server spec and client spec to get it working. - - -#========================================================================= - -# **** server1 spec file **** - -### Export volume "brick" with the contents of "/home/export" directory. -volume posix1 - type storage/posix # POSIX FS translator - option directory /home/export1 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick1 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix1 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24016 -# option client-volume-filename /etc/glusterfs/glusterfs-client.vol - subvolumes brick1 - option auth.addr.brick1.allow * # access to "brick" volume -end-volume - - -#========================================================================= - -# **** server2 spec file **** -volume posix2 - type storage/posix # POSIX FS translator - option directory /home/export2 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick2 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix2 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24017 - subvolumes brick2 - option auth.addr.brick2.allow * # Allow access to "brick" volume -end-volume - - -#========================================================================= - -# **** server3 spec file **** - -volume posix3 - type storage/posix # POSIX FS translator - option directory /home/export3 # Export this directory -end-volume - -### Add POSIX record locking support to the storage brick -volume brick3 - type features/posix-locks - option mandatory on # enables mandatory locking on all files - subvolumes posix3 -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24018 - subvolumes brick3 - option auth.addr.brick3.allow * # access to "brick" volume -end-volume - -#========================================================================= - -# *** server for namespace *** -### Export volume "brick" with the contents of "/home/export" directory. -volume brick-ns - type storage/posix # POSIX FS translator - option directory /home/export-ns # Export this directory -end-volume - -volume server - type protocol/server - option transport-type tcp # For TCP/IP transport - option transport.socket.listen-port 24019 - subvolumes brick-ns - option auth.addr.brick-ns.allow * # access to "brick" volume -end-volume - - -#========================================================================= - -# **** Clustered Client config file **** - -### Add client feature and attach to remote subvolume of server1 -volume client1 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24016 - option remote-subvolume brick1 # name of the remote volume -end-volume - -### Add client feature and attach to remote subvolume of server2 -volume client2 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24017 - option remote-subvolume brick2 # name of the remote volume -end-volume - -volume client3 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24018 - option remote-subvolume brick3 # name of the remote volume -end-volume - - -volume client-ns - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport - option remote-host 127.0.0.1 # IP address of the remote brick - option transport.socket.remote-port 24019 - option remote-subvolume brick-ns # name of the remote volume -end-volume - -### Add unify feature to cluster the servers. Associate an -### appropriate scheduler that matches your I/O demand. -volume bricks - type cluster/unify - option namespace client-ns # this will not be storage child of unify. - subvolumes client1 client2 client3 -### ** ALU Scheduler Option ** - option self-heal background # foreground off # default is foreground - option scheduler alu - option alu.limits.min-free-disk 5% #% - option alu.limits.max-open-files 10000 - option alu.order disk-usage:read-usage:write-usage:open-files-usage:disk-speed-usage - option alu.disk-usage.entry-threshold 2GB - option alu.disk-usage.exit-threshold 128MB - option alu.open-files-usage.entry-threshold 1024 - option alu.open-files-usage.exit-threshold 32 - option alu.read-usage.entry-threshold 20 #% - option alu.read-usage.exit-threshold 4 #% - option alu.write-usage.entry-threshold 20 #% - option alu.write-usage.exit-threshold 4 #% - option alu.disk-speed-usage.entry-threshold 0 # DO NOT SET IT. SPEED IS CONSTANT!!!. - option alu.disk-speed-usage.exit-threshold 0 # DO NOT SET IT. SPEED IS CONSTANT!!!. - option alu.stat-refresh.interval 10sec - option alu.stat-refresh.num-file-create 10 -### ** Random Scheduler ** -# option scheduler random -### ** NUFA Scheduler ** -# option scheduler nufa -# option nufa.local-volume-name posix1 -### ** Round Robin (RR) Scheduler ** -# option scheduler rr -# option rr.limits.min-free-disk 5% #% -end-volume - diff --git a/doc/examples/write-behind.vol b/doc/examples/write-behind.vol deleted file mode 100644 index 9c6bae11c53..00000000000 --- a/doc/examples/write-behind.vol +++ /dev/null @@ -1,26 +0,0 @@ -volume client - type protocol/client - option transport-type tcp # for TCP/IP transport - option remote-host 192.168.1.10 # IP address of the remote brick - option remote-subvolume brick # name of the remote volume -end-volume - -## In normal clustered storage type, any of the cluster translators can come here. -# -# Definition of other clients -# -# Definition of cluster translator (may be unify, replicate, or unify over replicate) -# - - -### 'Write-behind' translator is a performance booster for write operation. Best used on client side, as its main intension is to reduce the network latency caused for each write operation. - -volume wb - type performance/write-behind - subvolumes client # In this example it is 'client' you may have to change it according to your spec file. - option flush-behind on # default value is 'off' - option window-size 2MB - option aggregate-size 1MB # default value is 0 - option enable_O_SYNC no # default is no - option disable-for-first-nbytes 128KB #default is 1 -end-volume diff --git a/doc/features/ctime.md b/doc/features/ctime.md new file mode 100644 index 00000000000..74a77abed4b --- /dev/null +++ b/doc/features/ctime.md @@ -0,0 +1,68 @@ +# Consistent time attributes in gluster across replica/distribute + + +#### Problem: +Traditionally gluster has been using time attributes (ctime, atime, mtime) of files/dirs from bricks. The problem with this approach is that, it is not consisteant across replica and distribute bricks. And applications which depend on it breaks as replica might not always return time attributes from same brick. + +Tar especially gives "file changed as we read it" whenever it detects ctime differences when stat is served from different bricks. The way we have been trying to solve it is to serve the stat structures from same brick in afr, max-time in dht. But it doesn't avoid the problem completely. Because there is no way to change ctime at the moment(lutimes() only allows mtime, atime), there is little we can do to make sure ctimes match after self-heals/xattr updates/rebalance. + +#### Solution Proposed: +Store time attribues (ctime, mtime, atime) as an xattr of the file. The xattr is updated based +on the fop. If a filesystem fop changes only mtime and ctime, update only those in xattr for +that file. + +#### Design Overview: +1) As part of each fop, top layer will generate a time stamp and pass it to the down along + with other information + - This will bring a dependency for NTP synced clients along with servers + - There can be a diff in time if the fop stuck in the xlator for various reason, +for ex: because of locks. + + 2) On the server, posix layer stores the value in the memory (inode ctx) and will sync the data periodically to the disk as an extended attr + - Of course sync call also will force it. And fop comes for an inode which is not linked, we do the sync immediately. + + 3) Each time when inodes are created or initialized it read the data from disk and store in inode ctx. + + 4) Before setting to inode_ctx we compare the timestamp stored and the timestamp received, and only store if the stored value is lesser than the current value. + + 5) So in best case data will be stored and retrieved from the memory. We replace the values in iatt with the values in inode_ctx. + + 6) File ops that changes the parent directory attr time need to be consistent across all the distributed directories across the subvolumes. (for eg: a create call will change ctime and mtime of parent dir) + + - This has to handle separately because we only send the fop to the hashed subvolume. + - We can asynchronously send the timeupdate setattr fop to the other subvoumes and change the values for parent directory if the file fops is successful on hashed subvolume. + - This will have a window where the times are inconsistent across dht subvolume (Please provide your suggestions) + +7) Currently we have couple of mount options for time attributes like noatime, relatime , nodiratime etc. But we are not explicitly handled those options even if it is given as mount option when gluster mount. + + +#### Implementation Overview: +This features involves changes in following xlators. + - utime xlator + - posix xlator + +##### utime xlator: +This is a new client side xlator which does following tasks. + +1. It will generate a time stamp and passes it down in frame->root->ctime and over the network. +2. Based on fop, it also decides the time attributes to be updated and this passed using "frame->root->flags" + + Patches: + 1. https://review.gluster.org/#/c/19857/ + +##### posix xlator: +Following tasks are done in posix xlator: + +1. Provides APIs to set and get the xattr from backend. It also caches the xattr in inode context. During get, it updates time attributes stored in xattr into iatt structure. +2. Based on the flags from utime xlator, relevant fops update the time attributes in the xattr. + + Patches: + 1. https://review.gluster.org/#/c/19267/ + 2. https://review.gluster.org/#/c/19795/ + 3. https://review.gluster.org/#/c/19796/ + +#### Pending Work: +1. Handling of time related mount options (noatime, realatime,etc) +2. flag based create (depending on flags in open, create behaviour might change) +3. Changes in dht for direcotory sync acrosss multiple subvolumes +4. readdirp stat need to be worked on. diff --git a/doc/features/ganesha-ha.md b/doc/features/ganesha-ha.md new file mode 100644 index 00000000000..4b226a22ccf --- /dev/null +++ b/doc/features/ganesha-ha.md @@ -0,0 +1,43 @@ +# Overview of Ganesha HA Resource Agents in GlusterFS 3.7 + +The ganesha_mon RA monitors its ganesha.nfsd daemon. While the +daemon is running, it creates two attributes: ganesha-active and +grace-active. When the daemon stops for any reason, the attributes +are deleted. Deleting the ganesha-active attribute triggers the +failover of the virtual IP (the IPaddr RA) to another node — +according to constraint location rules — where ganesha.nfsd is +still running. + +The ganesha_grace RA monitors the grace-active attribute. When +the grace-active attibute is deleted, the ganesha_grace RA stops, +and will not restart. This triggers pacemaker to invoke the notify +action in the ganesha_grace RAs on the other nodes in the cluster; +which send a DBUS message to their respective ganesha.nfsd. + +(N.B. grace-active is a bit of a misnomer. while the grace-active +attribute exists, everything is normal and healthy. Deleting the +attribute triggers putting the surviving ganesha.nfsds into GRACE.) + +To ensure that the remaining/surviving ganesha.nfsds are put into + NFS-GRACE before the IPaddr (virtual IP) fails over there is a +short delay (sleep) between deleting the grace-active attribute +and the ganesha-active attribute. To summarize, e.g. in a four +node cluster: + +1. on node 2 ganesha_mon::monitor notices that ganesha.nfsd has died + +2. on node 2 ganesha_mon::monitor deletes its grace-active attribute + +3. on node 2 ganesha_grace::monitor notices that grace-active is gone +and returns OCF_ERR_GENERIC, a.k.a. new error. When pacemaker tries +to (re)start ganesha_grace, its start action will return +OCF_NOT_RUNNING, a.k.a. known error, don't attempt further restarts. + +4. on nodes 1, 3, and 4, ganesha_grace::notify receives a post-stop +notification indicating that node 2 is gone, and sends a DBUS message +to its ganesha.nfsd, putting it into NFS-GRACE. + +5. on node 2 ganesha_mon::monitor waits a short period, then deletes +its ganesha-active attribute. This triggers the IPaddr (virt IP) +failover according to constraint location rules. + diff --git a/doc/get_put_api_using_xattr.txt b/doc/get_put_api_using_xattr.txt deleted file mode 100644 index 58951f5bf4f..00000000000 --- a/doc/get_put_api_using_xattr.txt +++ /dev/null @@ -1,22 +0,0 @@ -GlusterFS get/put API interface provided through extended attributes: - -API usage: - int put(dirpath/filename, data): setfattr -n glusterfs.file.<filename> -v <data> <dirpath> - void *get(dirpath/filename): getfattr -n glusterfs.file.<filename> <dirpath> - - -internals: -* unify handling setxattr/getxattr - - setxattr - unify's setxattr forwards setxattr call to all the child nodes with XATTR_REPLACE flag, except namespace. setxattr will succeeds only on the child node on which the file already exists. if the setxattr operation fails on all child nodes, it indicates that the file does not already exist on any of the child nodes. unify follows the same rules as it follows for create, but using setxattr call itself with XATTR_CREATE flag. unify sends a setxattr to namespace first, with zero length data. if namespace setxattr succeeds, unify schedules setxattr to one of the child nodes. - - - getxattr - unify's getxattr forwards getxattr call to all the child nodes. wait for completion of operation on all the child nodes, and returns success if getxattr succeeded one child node. - -* posix handling setxattr/getxattr - - setxattr - posix setxattr does a open with O_CREAT|O_TRUNC on the <path>/<name>, writes value of the setxattr as data into the file and closes the file. when data is null, posix setxattr avoids doing write. file is closed after write. - - - getxattr - posix getxattr does open with O_RDONLY on the <path>/<name>, reads the complete content of the file. file is closed after read. - diff --git a/doc/gluster.8 b/doc/gluster.8 index ced265fe18f..ba595edca15 100644 --- a/doc/gluster.8 +++ b/doc/gluster.8 @@ -1,121 +1,355 @@ -.\" -.\" Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com> + +.\" Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> .\" This file is part of GlusterFS. .\" -.\" GlusterFS is GF_FREE software; you can redistribute it and/or modify -.\" it under the terms of the GNU Affero General Public License as published -.\" by the Free Software Foundation; either version 3 of the License, -.\" or (at your option) any later version. -.\" -.\" GlusterFS 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 -.\" Affero General Public License for more details. -.\" -.\" You should have received a copy of the GNU Affero General Public License -.\" along with this program. If not, see -.\" <http://www.gnu.org/licenses/>. +.\" This file is licensed to you under your choice of the GNU Lesser +.\" General Public License, version 3 or any later version (LGPLv3 or +.\" later), or the GNU General Public License, version 2 (GPLv2), in all +.\" cases as published by the Free Software Foundation. .\" .\" -.TH Gluster 8 "Gluster command line tool" "9 September 2010" "Gluster Inc." +.TH Gluster 8 "Gluster command line utility" "07 March 2011" "Gluster Inc." .SH NAME -Gluster \- Gluster command line tool. +gluster - Gluster Console Manager (command line utility) .SH SYNOPSIS .B gluster .PP -To enter gluster prompt +To run the program and display gluster prompt: +.PP +.B gluster [--remote-host=<gluster_node>] [--mode=script] [--xml] .PP (or) .PP - -.B gluster -.I [commands] [options] +To specify a command directly: .PP -Gluster is a command line tool for dynamic volume management for glusterfs. +.B gluster +.I [commands] [options] [--remote-host=<gluster_node>] [--mode=script] [--xml] .SH DESCRIPTION -Gluster command line tool is used for dynamic volume management. -The tool must be executed on any of the export servers. The cli gives an easy way to perform cloud operations such as volume create, volume expand, volume shrink, volume migrate, volume rebalance without the necessity of scheduling downtimes. +The Gluster Console Manager is a command line utility for elastic volume management. You can run the gluster command on any export server. The command enables administrators to perform cloud operations, such as creating, expanding, shrinking, rebalancing, and migrating volumes without needing to schedule server downtime. .SH COMMANDS -.PP -Mandatory or optional arguments to long options are also mandatory or optional -for any corresponding short options. -.SS "Basic commands" + +.SS "Volume Commands" .PP .TP \fB\ volume info [all|<VOLNAME>] \fR -list information of all volumes +Display information about all volumes, or the specified volume. +.TP +\fB\ volume list \fR +List all volumes in cluster .TP -\fB\ volume create <NEW-VOLNAME> [stripe <COUNT>] [replica <COUNT>] [transport <tcp|rdma>] <NEW-BRICK> ... \fR -create a new volume of specified type with mentioned bricks, with specified transport-type [default:tcp] +\fB\ volume status [all | <VOLNAME> [nfs|shd|<BRICK>|quotad]] [detail|clients|mem|inode|fd|callpool|tasks|client-list] \fR +Display status of all or specified volume(s)/brick +.TP +\fB\ volume create <NEW-VOLNAME> [stripe <COUNT>] [[replica <COUNT> [arbiter <COUNT>]]|[replica 2 thin-arbiter 1]] [disperse [<COUNT>]] [disperse-data <COUNT>] [redundancy <COUNT>] [transport <tcp|rdma|tcp,rdma>] <NEW-BRICK> ... <TA-BRICK> \fR +Create a new volume of the specified type using the specified bricks and transport type (the default transport type is tcp). +To create a volume with both transports (tcp and rdma), give 'transport tcp,rdma' as an option. .TP \fB\ volume delete <VOLNAME> \fR -delete volume specified by \fB\<VOLNAME>\fR +Delete the specified volume. .TP \fB\ volume start <VOLNAME> \fR -start volume specified by \fB\<VOLNAME>\fR +Start the specified volume. .TP \fB\ volume stop <VOLNAME> [force] \fR -stop volume specified by \fB\<VOLNAME>\fR +Stop the specified volume. +.TP +\fB\ volume set <VOLNAME> <OPTION> <PARAMETER> [<OPTION> <PARAMETER>] ... \fR +Set the volume options. +.TP +\fB\ volume get <VOLNAME/all> <OPTION/all> \fR +Get the value of the all options or given option for volume <VOLNAME> or all option. gluster volume get all all is to get all global options .TP -\fB\ volume rename <VOLNAME> <NEW-VOLNAME> \fR -rename volume \fB\<VOLNAME>\fR to \fB\<NEW-VOLNAME>\fR +\fB\ volume reset <VOLNAME> [option] [force] \fR +Reset all the reconfigured options +.TP +\fB\ volume barrier <VOLNAME> {enable|disable} \fR +Barrier/unbarrier file operations on a volume +.TP +\fB\ volume clear-locks <VOLNAME> <path> kind {blocked|granted|all}{inode [range]|entry [basename]|posix [range]} \fR +Clear locks held on path +.TP +\fB\ volume help \fR +Display help for the volume command. +.SS "Brick Commands" +.PP .TP \fB\ volume add-brick <VOLNAME> <NEW-BRICK> ... \fR -add brick to volume. if the volume is of the type replicate or stripe, then one need to provide bricks in multiple of replica count, or stripe count.\fB\<VOLNAME>\fR +Add the specified brick to the specified volume. .TP \fB\ volume remove-brick <VOLNAME> <BRICK> ... \fR -remove brick from volume. if the volume is of the type replicate or stripe, then one need to provide bricks in multiple of replica count, or stripe count. Note that with this option, your data in the bricks which are removed is not going to available. If you need to migrate data, then refer to 'replace-brick' option. \fB\<VOLNAME>\fR +Remove the specified brick from the specified volume. +.IP +.B Note: +If you remove the brick, the data stored in that brick will not be available. You can migrate data from one brick to another using +.B replace-brick +option. +.TP +\fB\ volume reset-brick <VOLNAME> <SOURCE-BRICK> {{start} | {<NEW-BRICK> commit}} \fR +Brings down or replaces the specified source brick with the new brick. +.TP +\fB\ volume replace-brick <VOLNAME> <SOURCE-BRICK> <NEW-BRICK> commit force \fR +Replace the specified source brick with a new brick. .TP \fB\ volume rebalance <VOLNAME> start \fR -start rebalance of volume \fB\<VOLNAME>\fR +Start rebalancing the specified volume. .TP \fB\ volume rebalance <VOLNAME> stop \fR -stop rebalance of volume \fB\<VOLNAME>\fR +Stop rebalancing the specified volume. .TP \fB\ volume rebalance <VOLNAME> status \fR -rebalance status of volume \fB<VOLNAME>\fR +Display the rebalance status of the specified volume. +.SS "Log Commands" .TP -\fB\ volume replace-brick <VOLNAME> (<BRICK> <NEW-BRICK>) start|pause|abort|status|commit \fR -replace-brick operations +\fB\ volume log filename <VOLNAME> [BRICK] <DIRECTORY> \fB +Set the log directory for the corresponding volume/brick. .TP -\fB\ volume set <VOLNAME> <OPTION> <VALUE> [<OPTION> <VALUE>] ... \fR -set transport type for volume \fB\<VOLNAME>\fR +\fB\ volume log locate <VOLNAME> [BRICK] \fB +Locate the log file for corresponding volume/brick. .TP -\fB\ volume help \fB -display help for the volume command +\fB\ volume log rotate <VOLNAME> [BRICK] \fB +Rotate the log file for corresponding volume/brick. .TP -\fB\ volume log filename <VOLNAME> [BRICK] <PATH> \fB -set the log file for corresponding volume/brick +\fB\ volume profile <VOLNAME> {start|info [peek|incremental [peek]|cumulative|clear]|stop} [nfs] \fR +Profile operations on the volume. Once started, volume profile <volname> info provides cumulative statistics of the FOPs performed. .TP -\fB\ volume log locate <VOLNAME> [BRICK] \fB -locate the log file for corresponding volume/brick +\fB\ volume top <VOLNAME> {open|read|write|opendir|readdir|clear} [nfs|brick <brick>] [list-cnt <value>] | {read-perf|write-perf} [bs <size> count <count>] [brick <brick>] [list-cnt <value>] \fR +Generates a profile of a volume representing the performance and bottlenecks/hotspots of each brick. .TP -\fB\ volume log rotate <VOLNAME> [BRICK] \fB -rotate the log file for corresponding volume/brick +\fB\ volume statedump <VOLNAME> [[nfs|quotad] [all|mem|iobuf|callpool|priv|fd|inode|history]... | [client <hostname:process-id>]] \fR +Dumps the in memory state of the specified process or the bricks of the volume. +.TP +\fB\ volume sync <HOSTNAME> [all|<VOLNAME>] \fR +Sync the volume information from a peer +.SS "Peer Commands" .TP \fB\ peer probe <HOSTNAME> \fR -probe peer specified by \fB\<HOSTNAME>\fR +Probe the specified peer. In case the <HOSTNAME> given belongs to an already probed peer, the peer probe command will add the hostname to the peer if required. .TP \fB\ peer detach <HOSTNAME> \fR -detach peer specified by \fB\<HOSTNAME>\fR +Detach the specified peer. .TP \fB\ peer status \fR -list status of peers +Display the status of peers. +.TP +\fB\ pool list \fR +List all the nodes in the pool (including localhost) .TP \fB\ peer help \fR -Help command for peer +Display help for the peer command. +.SS "Quota Commands" +.TP +\fB\ volume quota <VOLNAME> enable \fR +Enable quota on the specified volume. This will cause all the directories in the filesystem hierarchy to be accounted and updated thereafter on each operation in the the filesystem. To kick start this accounting, a crawl is done over the hierarchy with an auxiliary client. +.TP +\fB\ volume quota <VOLNAME> disable \fR +Disable quota on the volume. This will disable enforcement and accounting in the filesystem. Any configured limits will be lost. +.TP +\fB\ volume quota <VOLNAME> limit-usage <PATH> <SIZE> [<PERCENT>] \fR +Set a usage limit on the given path. Any previously set limit is overridden to the new value. The soft limit can optionally be specified (as a percentage of hard limit). If soft limit percentage is not provided the default soft limit value for the volume is used to decide the soft limit. +.TP +\fB\ volume quota <VOLNAME> limit-objects <PATH> <SIZE> [<PERCENT>] \fR +Set an inode limit on the given path. Any previously set limit is overridden to the new value. The soft limit can optionally be specified (as a percentage of hard limit). If soft limit percentage is not provided the default soft limit value for the volume is used to decide the soft limit. +.TP +NOTE: valid units of SIZE are : B, KB, MB, GB, TB, PB. If no unit is specified, the unit defaults to bytes. +.TP +\fB\ volume quota <VOLNAME> remove <PATH> \fR +Remove any usage limit configured on the specified directory. Note that if any limit is configured on the ancestors of this directory (previous directories along the path), they will still be honored and enforced. +.TP +\fB\ volume quota <VOLNAME> remove-objects <PATH> \fR +Remove any inode limit configured on the specified directory. Note that if any limit is configured on the ancestors of this directory (previous directories along the path), they will still be honored and enforced. +.TP +\fB\ volume quota <VOLNAME> list <PATH> \fR +Lists the usage and limits configured on directory(s). If a path is given only the limit that has been configured on the directory(if any) is displayed along with the directory's usage. If no path is given, usage and limits are displayed for all directories that has limits configured. +.TP +\fB\ volume quota <VOLNAME> list-objects <PATH> \fR +Lists the inode usage and inode limits configured on directory(s). If a path is given only the limit that has been configured on the directory(if any) is displayed along with the directory's inode usage. If no path is given, usage and limits are displayed for all directories that has limits configured. +.TP +\fB\ volume quota <VOLNAME> default-soft-limit <PERCENT> \fR +Set the percentage value for default soft limit for the volume. +.TP +\fB\ volume quota <VOLNAME> soft-timeout <TIME> \fR +Set the soft timeout for the volume. The interval in which limits are retested before the soft limit is breached. +.TP +\fB\ volume quota <VOLNAME> hard-timeout <TIME> \fR +Set the hard timeout for the volume. The interval in which limits are retested after the soft limit is breached. +.TP +\fB\ volume quota <VOLNAME> alert-time <TIME> \fR +Set the frequency in which warning messages need to be logged (in the brick logs) once soft limit is breached. +.TP +\fB\ volume inode-quota <VOLNAME> enable/disable \fR +Enable/disable inode-quota for <VOLNAME> +.TP +\fB\ volume quota help \fR +Display help for volume quota commands +.TP +NOTE: valid units of time and their symbols are : hours(h/hr), minutes(m/min), seconds(s/sec), weeks(w/wk), Days(d/days). +.SS "Geo-replication Commands" +.TP +\fI\ Note\fR: password-less ssh, from the master node (where these commands are executed) to the slave node <SLAVE_HOST>, is a prerequisite for the geo-replication commands. +.TP +\fB\ system:: execute gsec_create\fR +Generates pem keys which are required for push-pem +.TP +\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> create [[ssh-port n][[no-verify]|[push-pem]]] [force]\fR +Create a new geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>. +Use ssh-port n if custom SSH port is configured in slave nodes. +Use no-verify if the rsa-keys of nodes in master volume is distributed to slave nodes through an external agent. +Use push-pem to push the keys automatically. +.TP +\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> {start|stop} [force] \fR +Start/stop the geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>. +.TP +\fB\ volume geo-replication [<MASTER_VOL> [<SLAVE_HOST>::<SLAVE_VOL>]] status [detail] \fR +Query status of the geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>. +.TP +\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> {pause|resume} [force] \fR +Pause/resume the geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>. +.TP +\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> delete [reset-sync-time]\fR +Delete the geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>. +Optionally you can also reset the sync time in case you need to resync the entire volume on session recreate. +.TP +\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> config [[!]<options> [<value>]] \fR +View (when no option provided) or set configuration for this geo-replication session. +Use "!<OPTION>" to reset option <OPTION> to default value. +.SS "Bitrot Commands" +.TP +\fB\ volume bitrot <VOLNAME> {enable|disable} \fR +Enable/disable bitrot for volume <VOLNAME> +.TP +\fB\ volume bitrot <VOLNAME> signing-time <time-in-secs> \fR +Waiting time for an object after last fd is closed to start signing process. +.TP +\fB\ volume bitrot <VOLNAME> signer-threads <count> \fR +Number of signing process threads. Usually set to number of available cores. +.TP +\fB\ volume bitrot <VOLNAME> scrub-throttle {lazy|normal|aggressive} \fR +Scrub-throttle value is a measure of how fast or slow the scrubber scrubs the filesystem for volume <VOLNAME> +.TP +\fB\ volume bitrot <VOLNAME> scrub-frequency {hourly|daily|weekly|biweekly|monthly} \fR +Scrub frequency for volume <VOLNAME> +.TP +\fB\ volume bitrot <VOLNAME> scrub {pause|resume|status|ondemand} \fR +Pause/Resume scrub. Upon resume, scrubber continues where it left off. status option shows the statistics of scrubber. ondemand option starts the scrubbing immediately if the scrubber is not paused or already running. +.TP +\fB\ volume bitrot help \fR +Display help for volume bitrot commands +.TP +.SS "Snapshot Commands" +.TP +\fB\ snapshot create <snapname> <volname> [no-timestamp] [description <description>] [force] \fR +Creates a snapshot of a GlusterFS volume. User can provide a snap-name and a description to identify the snap. Snap will be created by appending timestamp in GMT. User can override this behaviour using "no-timestamp" option. The description cannot be more than 1024 characters. To be able to take a snapshot, volume should be present and it should be in started state. +.TP +\fB\ snapshot restore <snapname> \fR +Restores an already taken snapshot of a GlusterFS volume. Snapshot restore is an offline activity therefore if the volume is online (in started state) then the restore operation will fail. Once the snapshot is restored it will not be available in the list of snapshots. +.TP +\fB\ snapshot clone <clonename> <snapname> \fR +Create a clone of a snapshot volume, the resulting volume will be GlusterFS volume. User can provide a clone-name. To be able to take a clone, snapshot should be present and it should be in activated state. +.TP +\fB\ snapshot delete ( all | <snapname> | volume <volname> ) \fR +If snapname is specified then mentioned snapshot is deleted. If volname is specified then all snapshots belonging to that particular volume is deleted. If keyword *all* is used then all snapshots belonging to the system is deleted. +.TP +\fB\ snapshot list [volname] \fR +Lists all snapshots taken. If volname is provided, then only the snapshots belonging to that particular volume is listed. +.TP +\fB\ snapshot info [snapname | (volume <volname>)] \fR +This command gives information such as snapshot name, snapshot UUID, time at which snapshot was created, and it lists down the snap-volume-name, number of snapshots already taken and number of snapshots still available for that particular volume, and the state of the snapshot. If snapname is specified then info of the mentioned snapshot is displayed. If volname is specified then info of all snapshots belonging to that volume is displayed. If both snapname and volname is not specified then info of all the snapshots present in the system are displayed. +.TP +\fB\ snapshot status [snapname | (volume <volname>)] \fR +This command gives status of the snapshot. The details included are snapshot brick path, volume group(LVM details), status of the snapshot bricks, PID of the bricks, data percentage filled for that particular volume group to which the snapshots belong to, and total size of the logical volume. + +If snapname is specified then status of the mentioned snapshot is displayed. If volname is specified then status of all snapshots belonging to that volume is displayed. If both snapname and volname is not specified then status of all the snapshots present in the system are displayed. +.TP +\fB\ snapshot config [volname] ([snap-max-hard-limit <count>] [snap-max-soft-limit <percent>]) | ([auto-delete <enable|disable>]) | ([activate-on-create <enable|disable>]) +Displays and sets the snapshot config values. + +snapshot config without any keywords displays the snapshot config values of all volumes in the system. If volname is provided, then the snapshot config values of that volume is displayed. + +Snapshot config command along with keywords can be used to change the existing config values. If volname is provided then config value of that volume is changed, else it will set/change the system limit. + +snap-max-soft-limit and auto-delete are global options, that will be inherited by all volumes in the system and cannot be set to individual volumes. + +snap-max-hard-limit can be set globally, as well as per volume. The lowest limit between the global system limit and the volume specific limit, becomes the +"Effective snap-max-hard-limit" for a volume. + +snap-max-soft-limit is a percentage value, which is applied on the "Effective snap-max-hard-limit" to get the "Effective snap-max-soft-limit". + +When auto-delete feature is enabled, then upon reaching the "Effective snap-max-soft-limit", with every successful snapshot creation, the oldest snapshot will be deleted. + +When auto-delete feature is disabled, then upon reaching the "Effective snap-max-soft-limit", the user gets a warning with every successful snapshot creation. + +When auto-delete feature is disabled, then upon reaching the "Effective snap-max-hard-limit", further snapshot creations will not be allowed. + +activate-on-create is disabled by default. If you enable activate-on-create, then further snapshot will be activated during the time of snapshot creation. +.TP +\fB\ snapshot activate <snapname> \fR +Activates the mentioned snapshot. + +Note : By default the snapshot is activated during snapshot creation. +.TP +\fB\ snapshot deactivate <snapname> \fR +Deactivates the mentioned snapshot. +.TP +\fB\ snapshot help \fR +Display help for the snapshot commands. +.SS "Self-heal Commands" +.TP +\fB\ volume heal <VOLNAME>\fR +Triggers index self heal for the files that need healing. + +.TP +\fB\ volume heal <VOLNAME> [enable | disable]\fR +Enable/disable self-heal-daemon for volume <VOLNAME>. + +.TP +\fB\ volume heal <VOLNAME> full\fR +Triggers self heal on all the files. + +.TP +\fB\ volume heal <VOLNAME> info \fR +Lists the files that need healing. + +.TP +\fB\ volume heal <VOLNAME> info split-brain \fR +Lists the files which are in split-brain state. + +.TP +\fB\ volume heal <VOLNAME> statistics \fR +Lists the crawl statistics. + +.TP +\fB\ volume heal <VOLNAME> statistics heal-count \fR +Displays the count of files to be healed. + +.TP +\fB\ volume heal <VOLNAME> statistics heal-count replica <HOSTNAME:BRICKNAME> \fR +Displays the number of files to be healed from a particular replica subvolume to which the brick <HOSTNAME:BRICKNAME> belongs. + +.TP +\fB\ volume heal <VOLNAME> split-brain bigger-file <FILE> \fR +Performs healing of <FILE> which is in split-brain by choosing the bigger file in the replica as source. + +.TP +\fB\ volume heal <VOLNAME> split-brain source-brick <HOSTNAME:BRICKNAME> \fR +Selects <HOSTNAME:BRICKNAME> as the source for all the files that are in split-brain in that replica and heals them. + +.TP +\fB\ volume heal <VOLNAME> split-brain source-brick <HOSTNAME:BRICKNAME> <FILE> \fR +Selects the split-brained <FILE> present in <HOSTNAME:BRICKNAME> as source and completes heal. +.SS "Other Commands" +.TP +\fB\ get-state [<daemon>] [[odir </path/to/output/dir/>] [file <filename>]] [detail|volumeoptions] \fR +Get local state representation of mentioned daemon and store data in provided path information .TP \fB\ help \fR -display command options +Display the command options. .TP \fB\ quit \fR -quit -.TP -.PP -.SH FILES -/etc/glusterd/* +Exit the gluster command line interface. +.SH FILES +/var/lib/glusterd/* .SH SEE ALSO .nf \fBfusermount\fR(1), \fBmount.glusterfs\fR(8), \fBglusterfs\fR(8), \fBglusterd\fR(8) @@ -124,5 +358,3 @@ quit .SH COPYRIGHT .nf Copyright(c) 2006-2011 Gluster, Inc. <http://www.gluster.com> - -.fi diff --git a/doc/glusterd.8 b/doc/glusterd.8 index 254542f8174..e3768c78761 100644 --- a/doc/glusterd.8 +++ b/doc/glusterd.8 @@ -1,76 +1,59 @@ .\" -.\" Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com> +.\" Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> .\" This file is part of GlusterFS. .\" -.\" GlusterFS is GF_FREE software; you can redistribute it and/or modify -.\" it under the terms of the GNU Affero General Public License as published -.\" by the Free Software Foundation; either version 3 of the License, -.\" or (at your option) any later version. -.\" -.\" GlusterFS 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 -.\" Affero General Public License for more details. -.\" -.\" You should have received a copy of the GNU Affero General Public License -.\" along with this program. If not, see -.\" <http://www.gnu.org/licenses/>. +.\" This file is licensed to you under your choice of the GNU Lesser +.\" General Public License, version 3 or any later version (LGPLv3 or +.\" later), or the GNU General Public License, version 2 (GPLv2), in all +.\" cases as published by the Free Software Foundation. .\" .\" -.TH Glusterd 8 "Gluster dynamic volume management Daemon" "9 September 2010" "Gluster Inc." +.TH Glusterd 8 "Gluster elastic volume management daemon" "07 March 2011" "Gluster Inc." .SH NAME -Glusterd \- Gluster dynamic volume management Daemon. +Glusterd \- Gluster elastic volume management daemon .SH SYNOPSIS .B glusterd -.PP -(or) -.B glusterd .I [OPTION...] -.PP -Glusterd is a daemon for dynamic volume management for glusterfs. .SH DESCRIPTION -Gluster daemon is used for dynamic volume management. -The daemon must be executed on all of the export servers. +The glusterd daemon is used for elastic volume management. The daemon must be run on all export servers. .SH OPTIONS -.PP -Mandatory or optional arguments to long options are also mandatory or optional -for any corresponding short options. + .SS "Basic options" .PP .TP -\fB\-l, \fB\-\-log\-file=LOGFILE\fR -File to use for logging [default:/usr/local/var/log/glusterfs/glusterfs.log] +\fB\-l <LOGFILE>, \fB\-\-log\-file=<LOGFILE>\fR +File to use for logging. +.TP +\fB\-L <LOGLEVEL>, \fB\-\-log\-level=<LOGLEVEL>\fR +Logging severity. Valid options are TRACE, DEBUG, INFO, WARNING, ERROR and CRITICAL (the default is INFO). .TP -\fB\-L, \fB\-\-log\-level=LOGLEVEL\fR -Logging severity. Valid options are TRACE, DEBUG, NORMAL, WARNING, -ERROR and CRITICAL [default: NORMAL] +\fB\-\-localtime\-logging\fR +Enable localtime log timestamps. .TP \fB\-\-debug\fR -Run in debug mode. This option sets \fB\-\-no\-daemon\fR, \fB\-\-log\-level\fR to DEBUG -and \fB\-\-log\-file\fR to console +Run the program in debug mode. This option sets \fB\-\-no\-daemon\fR, \fB\-\-log\-level\fR to DEBUG +and \fB\-\-log\-file\fR to console. .TP \fB\-N, \fB\-\-no\-daemon\fR -Run in foreground -.TP +Run the program in the foreground. -.TP -.SS Miscellaneous Options: +.SS "Miscellaneous Options:" .TP \fB\-?, \fB\-\-help\fR -Give this help list +Display this help. .TP \fB\-\-usage\fR -Give a short usage message +Display a short usage message. .TP \fB\-V, \fB\-\-version\fR -Print program version +Print the program version. .PP .SH FILES -/etc/glusterd/* +/var/lib/glusterd/* .SH SEE ALSO .nf diff --git a/doc/glusterd.vol b/doc/glusterd.vol deleted file mode 100644 index 4e43fb0dad2..00000000000 --- a/doc/glusterd.vol +++ /dev/null @@ -1,8 +0,0 @@ -volume management - type mgmt/glusterd - option working-directory /etc/glusterd - option transport-type socket,rdma - option transport.socket.keepalive-time 10 - option transport.socket.keepalive-interval 2 -end-volume - diff --git a/doc/glusterfs.8 b/doc/glusterfs.8 index 278c54504e2..3d359ea85e4 100644 --- a/doc/glusterfs.8 +++ b/doc/glusterfs.8 @@ -1,123 +1,173 @@ -.\" Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com> +.\" Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> .\" This file is part of GlusterFS. .\" -.\" GlusterFS is free software; you can redistribute it and/or modify -.\" it under the terms of the GNU Affero General Public License as published -.\" by the Free Software Foundation; either version 3 of the License, -.\" or (at your option) any later version. +.\" This file is licensed to you under your choice of the GNU Lesser +.\" General Public License, version 3 or any later version (LGPLv3 or +.\" later), or the GNU General Public License, version 2 (GPLv2), in all +.\" cases as published by the Free Software Foundation. .\" -.\" GlusterFS 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 -.\" Affero General Public License for more details. .\" -.\" You should have received a copy of the GNU Affero General Public License -.\" long with this program. If not, see -.\" <http://www.gnu.org/licenses/>. .\" -.\" -.\" -.TH GlusterFS 8 "Cluster Filesystem" "19 March 2010" "Gluster Inc." +.TH GlusterFS 8 "Clustered File System" "07 March 2011" "Gluster Inc." .SH NAME -GlusterFS \- Clustered Filesystem. +GlusterFS \- clustered file system .SH SYNOPSIS .B glusterfs .I [options] [mountpoint] .PP .SH DESCRIPTION -GlusterFS is a clustered file-system capable of scaling to several peta-bytes. -It aggregates various storage bricks over Infiniband RDMA or TCP/IP +GlusterFS is a clustered file system, capable of scaling to several peta-bytes. +It aggregates various storage bricks over Infiniband RDMA or TCP/IP and interconnect into one large parallel network file system. Storage bricks can -be made of any commodity hardware such as x86-64 server with SATA-II RAID and +be made of any commodity hardware, such as x86-64 server with SATA-II RAID and Infiniband HBA. -GlusterFS is fully POSIX compliant FileSystem. On client side, it has dependency -on FUSE package, on server side, it works seemlessly on different OSes. -(Currently supported on GNU/Linux, Solaris). +GlusterFS is fully POSIX compliant file system. On client side, it has dependency +on FUSE package, on server side, it works seemlessly on different operating systems. +Currently supported on GNU/Linux and Solaris. .SH OPTIONS -.PP -Mandatory or optional arguments to long options are also mandatory or optional -for any corresponding short options. + .SS "Basic options" .PP .TP - \fB\-f, \fB\-\-volfile=VOLUME-FILE\fR -File to use as VOLUME-FILE [default:/etc/glusterfs/glusterfs.vol] +File to use as VOLUME-FILE. .TP \fB\-l, \fB\-\-log\-file=LOGFILE\fR -File to use for logging [default:/var/log/glusterfs/glusterfs.log] +File to use for logging (the default is <INSTALL-DIR>/var/log/glusterfs/<MOUNT-POINT>.log). .TP \fB\-L, \fB\-\-log\-level=LOGLEVEL\fR -Logging severity. Valid options are TRACE, DEBUG, NORMAL, WARNING, ERROR and -CRITICAL [default: WARNING] +Logging severity. Valid options are TRACE, DEBUG, INFO, WARNING, ERROR and CRITICAL (the default is INFO). .TP \fB\-s, \fB\-\-volfile\-server=SERVER\fR -Server to get the volume from. This option overrides \fB\-\-volfile option +Server to get the volume from. This option overrides \fB\-\-volfile \fR option. +.TP +\fB\-\-volfile\-max\-fetch\-attempts=MAX\-ATTEMPTS\fR +Maximum number of connect attempts to server. This option should be provided with +\fB\-\-volfile\-server\fR option (the default is 1). .SS "Advanced options" .PP .TP - +\fB\-\-acl\fR +Mount the filesystem with POSIX ACL support. +.TP +\fB\-\-localtime\-logging\fR +Enable localtime log timestamps. +.TP \fB\-\-debug\fR -Run in debug mode. This option sets \fB\-\-no\-daemon\fR, \fB\-\-log\-level\fR to DEBUG -and \fB\-\-log\-file\fR to console +Run in debug mode. This option sets \fB\-\-no\-daemon\fR, \fB\-\-log\-level\fR to DEBUG, +and \fB\-\-log\-file\fR to console. +.TP +\fB\-\-enable\-ino32=BOOL\fR +Use 32-bit inodes when mounting to workaround application that doesn't support 64-bit inodes. +.TP +\fB\-\-fopen\-keep\-cache[=BOOL]\fR +Do not purge the cache on file open (default: false). +.TP +\fB\-\-mac\-compat=BOOL\fR +Provide stubs for attributes needed for seamless operation on Macs (the default is off). .TP \fB\-N, \fB\-\-no\-daemon\fR -Run in foreground +Run in the foreground. +.TP +\fB\-p, \fB\-\-pid\-file=PIDFILE\fR +File to use as PID file. .TP \fB\-\-read\-only\fR -Makes the filesystem read-only +Mount the file system in 'read-only' mode. .TP -\fB\-p, \fB\-\-pid\-file=PIDFILE\fR -File to use as pid file +\fB\-\-selinux\fR +Enable SELinux label (extended attributes) support on inodes. +.TP +\fB\-S, \fB\-\-socket\-file=SOCKFILE\fR +File to use as unix-socket. .TP \fB\-\-volfile\-id=KEY\fR -KEY of the volume file to be fetched from server +Key of the volume file to be fetched from the server. .TP \fB\-\-volfile\-server\-port=PORT\fR -Port number of volfile server +Port number of volfile server. .TP \fB\-\-volfile\-server\-transport=TRANSPORT\fR -Transport type to get volume file from server [default: socket] +Transport type to get volume file from server (the default is tcp). .TP \fB\-\-volume\-name=VOLUME\-NAME\fR -Volume name to be used for MOUNT-POINT [default: top most volume in -VOLUME-FILE] +Volume name to be used for MOUNT-POINT (the default is top most volume in VOLUME-FILE). +.TP +\fB\-\-worm\fR +Mount the filesystem in 'worm' mode. .TP \fB\-\-xlator\-option=VOLUME\-NAME.OPTION=VALUE\fR -Add/override a translator option for a volume with the specified value +Add/Override a translator option for a volume with the specified value. +.TP +\fB\-\-subdir\-mount=SUBDIR\-MOUNT\-PATH\fR +Mount subdirectory instead of the '/' of volume. .SS "Fuse options" .PP .TP +\fB\-\-attr\-times\-granularity=NANOSECONDS\fR +Declare supported granularity of file attribute times (default is 0 which kernel handles as unspecified; valid real values are between 1 and 1000000000). +.TP \fB\-\-attribute\-timeout=SECONDS\fR -Set attribute timeout to SECONDS for inodes in fuse kernel module [default: 1] +Set attribute timeout to SECONDS for inodes in fuse kernel module (the default is 1). +.TP +\fB\-\-background\-qlen=N\fR +Set fuse module's background queue length to N (the default is 64). +.TP +\fB\-\-congestion\-threshold=N\fR +Set fuse module's congestion threshold to N (the default is 48). +.TP +\fB\-\-direct\-io\-mode=BOOL|auto\fR +Specify fuse direct I/O strategy (the default is auto). +.TP +\fB\-\-dump-fuse=PATH\f\R +Dump fuse traffic to PATH .TP \fB\-\-entry\-timeout=SECONDS\fR -Set entry timeout to SECONDS in fuse kernel module [default: 1] +Set entry timeout to SECONDS in fuse kernel module (the default is 1). +.TP +\fB\-\-gid\-timeout=SECONDS\fR +Set auxiliary group list timeout to SECONDS for fuse translator (the default is 0). +.TP +\fB\-\-kernel-writeback-cache=BOOL\fR +Enable fuse in-kernel writeback cache. .TP -\fB\-\-direct\-io\-mode=BOOL\fR -Enable/Disable direct-io mode in fuse module [default: enable] +\fB\-\-negative\-timeout=SECONDS\fR +Set negative timeout to SECONDS in fuse kernel module (the default is 0). +.TP +\fB\-\-auto\-invalidation=BOOL\fR +controls whether fuse-kernel can auto-invalidate attribute, dentry and +page-cache. Disable this only if same files/directories are not +accessed across two different mounts concurrently [default: on]. +.TP +\fB\-\-volfile-check\fR +Enable strict volume file checking. .SS "Miscellaneous Options" .PP .TP \fB\-?, \fB\-\-help\fR -Give this help list +Display this help. .TP \fB\-\-usage\fR -Give a short usage message +Display a short usage message. .TP \fB\-V, \fB\-\-version\fR -Print program version +Print the program version. .PP .SH FILES -/etc/glusterfs/*.vol +/var/lib/glusterd/vols/*/*.vol +.SH EXAMPLES +mount a volume named foo on server bar with log level DEBUG on mount point +/mnt/foo + +# glusterfs \-\-log\-level=DEBUG \-\-volfile\-id=foo \-\-volfile\-server=bar /mnt/foo .SH SEE ALSO .nf @@ -126,6 +176,6 @@ Print program version .fi .SH COPYRIGHT .nf -Copyright(c) 2006-2011 Gluster, Inc. <http://www.gluster.com> +Copyright(c) 2006-2011 Red Hat, Inc. <http://www.redhat.com> \fR .fi diff --git a/doc/glusterfs.vol.sample b/doc/glusterfs.vol.sample deleted file mode 100644 index 3b1f1851722..00000000000 --- a/doc/glusterfs.vol.sample +++ /dev/null @@ -1,61 +0,0 @@ -### file: client-volume.vol.sample - -##################################### -### GlusterFS Client Volume File ## -##################################### - -#### CONFIG FILE RULES: -### "#" is comment character. -### - Config file is case sensitive -### - Options within a volume block can be in any order. -### - Spaces or tabs are used as delimitter within a line. -### - Each option should end within a line. -### - Missing or commented fields will assume default values. -### - Blank/commented lines are allowed. -### - Sub-volumes should already be defined above before referring. - -### Add client feature and attach to remote subvolume -volume client - type protocol/client - option transport-type tcp -# option transport-type unix -# option transport-type ib-sdp - option remote-host 127.0.0.1 # IP address of the remote brick -# option transport.socket.remote-port 24016 - -# option transport-type ib-verbs -# option transport.ib-verbs.remote-port 24016 -# option transport.ib-verbs.work-request-send-size 1048576 -# option transport.ib-verbs.work-request-send-count 16 -# option transport.ib-verbs.work-request-recv-size 1048576 -# option transport.ib-verbs.work-request-recv-count 16 - -# option transport-timeout 30 # seconds to wait for a reply - # from server for each request - option remote-subvolume brick # name of the remote volume -end-volume - -### Add readahead feature -#volume readahead -# type performance/read-ahead -# option page-size 1MB # unit in bytes -# option page-count 2 # cache per file = (page-count x page-size) -# subvolumes client -#end-volume - -### Add IO-Cache feature -#volume iocache -# type performance/io-cache -# option page-size 256KB -# option page-count 2 -# subvolumes readahead -#end-volume - -### Add writeback feature -#volume writeback -# type performance/write-behind -# option aggregate-size 1MB -# option window-size 2MB -# option flush-behind off -# subvolumes iocache -#end-volume diff --git a/doc/glusterfsd.8 b/doc/glusterfsd.8 index 186342d1044..bc1de2a8c80 100644 --- a/doc/glusterfsd.8 +++ b/doc/glusterfsd.8 @@ -1,19 +1,10 @@ -.\" Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com> +.\" Copyright (c) 20088888888-2012 Red Hat, Inc. <http://www.redhat.com> .\" This file is part of GlusterFS. .\" -.\" GlusterFS is free software; you can redistribute it and/or modify -.\" it under the terms of the GNU Affero General Public License as published -.\" by the Free Software Foundation; either version 3 of the License, -.\" or (at your option) any later version. -.\" -.\" GlusterFS 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 -.\" Affero General Public License for more details. -.\" -.\" You should have received a copy of the GNU Affero General Public License -.\" long with this program. If not, see -.\" <http://www.gnu.org/licenses/>. +.\" This file is licensed to you under your choice of the GNU Lesser +.\" General Public License, version 3 or any later version (LGPLv3 or +.\" later), or the GNU General Public License, version 2 (GPLv2), in all +.\" cases as published by the Free Software Foundation. .\" .\" .\" @@ -50,7 +41,7 @@ File to use as VOLUME-FILE [default:/etc/glusterfs/glusterfs.vol] File to use for logging [default:/var/log/glusterfs/glusterfs.log] .TP \fB\-L, \fB\-\-log\-level=LOGLEVEL\fR -Logging severity. Valid options are TRACE, DEBUG, NORMAL, WARNING, ERROR and +Logging severity. Valid options are TRACE, DEBUG, INFO, WARNING, ERROR and CRITICAL [default: WARNING] .TP \fB\-s, \fB\-\-volfile\-server=SERVER\fR @@ -60,6 +51,9 @@ Server to get the volume from. This option overrides \fB\-\-volfile option .PP .TP +\fB\-\-localtime\-logging\fR +Enable localtime log timestamps. +.TP \fB\-\-debug\fR Run in debug mode. This option sets \fB\-\-no\-daemon\fR, \fB\-\-log\-level\fR to DEBUG and \fB\-\-log\-file\fR to console @@ -73,6 +67,15 @@ Makes the filesystem read-only \fB\-p, \fB\-\-pid\-file=PIDFILE\fR File to use as pid file .TP +\fB\-S SOCKFILE +Socket file to used for inter-process communication +.TP +\fB\-\-brick\-name DIRECTORY +Directory to be used as export directory for GlusterFS +.TP +\fB\-\-brick\-port PORT +Brick Port to be registered with Gluster portmapper +.TP \fB\-\-volfile\-id=KEY\fR KEY of the volume file to be fetched from server .TP @@ -80,7 +83,7 @@ KEY of the volume file to be fetched from server Port number of volfile server .TP \fB\-\-volfile\-server\-transport=TRANSPORT\fR -Transport type to get volume file from server [default: socket] +Transport type to get volume file from server [default: tcp] .TP \fB\-\-volume\-name=VOLUME\-NAME\fR Volume name to be used for MOUNT-POINT [default: top most volume in @@ -101,6 +104,14 @@ Set entry timeout to SECONDS in fuse kernel module [default: 1] .TP \fB\-\-direct\-io\-mode=BOOL\fR Enable/Disable direct-io mode in fuse module [default: enable] +.TP +\fB\-\-resolve-gids\fR +Resolve all auxiliary groups in fuse translator (max 32 otherwise) +.TP +\fB\-\-auto\-invalidation=BOOL\fR +controls whether fuse-kernel can auto-invalidate attribute, dentry and +page-cache. Disable this only if same files/directories are not +accessed across two different mounts concurrently [default: on] .SS "Miscellaneous Options" .PP @@ -119,6 +130,11 @@ Print program version .SH FILES /etc/glusterfs/*.vol +.SH EXAMPLES +Start a GlusterFS server on localhost with volume name foo + +glusterfsd \-s localhost \-\-volfile\-id foo.server.media-disk\-1 \-p /var/lib/glusterd/vols/foo/run/server\-media\-disk\-1.pid \-S /tmp/<uniqueid>.socket \-\-brick-name /media/disk\-1 \-l /var/log/glusterfs/bricks/media\-disk\-1.log \-\-brick\-port 24009 \-\-xlator\-option foo\-server.listen-port=24009 + .SH SEE ALSO .nf \fBfusermount\fR(1), \fBmount.glusterfs\fR(8), \fBgluster\fR(8) diff --git a/doc/glusterfsd.vol.sample b/doc/glusterfsd.vol.sample deleted file mode 100644 index e91df3290a9..00000000000 --- a/doc/glusterfsd.vol.sample +++ /dev/null @@ -1,47 +0,0 @@ -### file: server-volume.vol.sample - -##################################### -### GlusterFS Server Volume File ## -##################################### - -#### CONFIG FILE RULES: -### "#" is comment character. -### - Config file is case sensitive -### - Options within a volume block can be in any order. -### - Spaces or tabs are used as delimitter within a line. -### - Multiple values to options will be : delimitted. -### - Each option should end within a line. -### - Missing or commented fields will assume default values. -### - Blank/commented lines are allowed. -### - Sub-volumes should already be defined above before referring. - -### Export volume "brick" with the contents of "/home/export" directory. -volume brick - type storage/posix # POSIX FS translator - option directory /home/export # Export this directory -end-volume - -### Add network serving capability to above brick. -volume server - type protocol/server - option transport-type tcp -# option transport-type unix -# option transport-type ib-sdp -# option transport.socket.bind-address 192.168.1.10 # Default is to listen on all interfaces -# option transport.socket.listen-port 24016 - -# option transport-type ib-verbs -# option transport.ib-verbs.bind-address 192.168.1.10 # Default is to listen on all interfaces -# option transport.ib-verbs.listen-port 24016 -# option transport.ib-verbs.work-request-send-size 131072 -# option transport.ib-verbs.work-request-send-count 64 -# option transport.ib-verbs.work-request-recv-size 131072 -# option transport.ib-verbs.work-request-recv-count 64 - -# option client-volume-filename /etc/glusterfs/glusterfs-client.vol - subvolumes brick -# NOTE: Access to any volume through protocol/server is denied by -# default. You need to explicitly grant access through # "auth" -# option. - option auth.addr.brick.allow * # Allow access to "brick" volume -end-volume diff --git a/doc/hacker-guide/Makefile.am b/doc/hacker-guide/Makefile.am deleted file mode 100644 index 65c92ac235e..00000000000 --- a/doc/hacker-guide/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -EXTRA_DIST = replicate.txt bdb.txt posix.txt call-stub.txt write-behind.txt - -#EXTRA_DIST = hacker-guide.tex afr.txt bdb.txt posix.txt call-stub.txt write-behind.txt -#hacker_guidedir = $(docdir) -#hacker_guide_DATA = hacker-guide.pdf - -#hacker-guide.pdf: $(EXTRA_DIST) -# pdflatex $(srcdir)/hacker-guide.tex diff --git a/doc/hacker-guide/adding-fops.txt b/doc/hacker-guide/adding-fops.txt deleted file mode 100644 index e70dbbdc829..00000000000 --- a/doc/hacker-guide/adding-fops.txt +++ /dev/null @@ -1,33 +0,0 @@ - HOW TO ADD A NEW FOP TO GlusterFS - ================================= - -Steps to be followed when adding a new FOP to GlusterFS: - -1. Edit glusterfs.h and add a GF_FOP_* constant. - -2. Edit xlator.[ch] and: - 2a. add the new prototype for fop and callback. - 2b. edit xlator_fops structure. - -3. Edit xlator.c and add to fill_defaults. - -4. Edit protocol.h and add struct necessary for the new FOP. - -5. Edit defaults.[ch] and provide default implementation. - -6. Edit call-stub.[ch] and provide stub implementation. - -7. Edit common-utils.c and add to gf_global_variable_init(). - -8. Edit client-protocol and add your FOP. - -9. Edit server-protocol and add your FOP. - -10. Implement your FOP in any translator for which the default implementation - is not sufficient. - -========================================== -Last updated: Mon Oct 27 21:35:49 IST 2008 - -Author: Vikas Gorur <vikas@gluster.com> -========================================== diff --git a/doc/hacker-guide/bdb.txt b/doc/hacker-guide/bdb.txt deleted file mode 100644 index fd0bd365206..00000000000 --- a/doc/hacker-guide/bdb.txt +++ /dev/null @@ -1,70 +0,0 @@ - -* How does file translates to key/value pair? ---------------------------------------------- - - in bdb a file is identified by key (obtained by taking basename() of the path of -the file) and file contents are stored as value corresponding to the key in database -file (defaults to glusterfs_storage.db under dirname() directory). - -* symlinks, directories ------------------------ - - symlinks and directories are stored as is. - -* db (database) files ---------------------- - - every directory, including root directory, contains a database file called -glusterfs_storage.db. all the regular files contained in the directory are stored -as key/value pair inside the glusterfs_storage.db. - -* internal data cache ---------------------- - - db does not provide a way to find out the size of the value corresponding to a key. -so, bdb makes DB->get() call for key and takes the length of the value returned. -since DB->get() also returns file contents for key, bdb maintains an internal cache and -stores the file contents in the cache. - every directory maintains a seperate cache. - -* inode number transformation ------------------------------ - - bdb allocates a inode number to each file and directory on its own. bdb maintains a -global counter and increments it after allocating inode number for each file -(regular, symlink or directory). NOTE: bdb does not guarantee persistent inode numbers. - -* checkpoint thread -------------------- - - bdb creates a checkpoint thread at the time of init(). checkpoint thread does a -periodic checkpoint on the DB_ENV. checkpoint is the mechanism, provided by db, to -forcefully commit the logged transactions to the storage. - -NOTES ABOUT FOPS: ------------------ - -lookup() - - 1> do lstat() on the path, if lstat fails, we assume that the file being looked up - is either a regular file or doesn't exist. - 2> lookup in the DB of parent directory for key corresponding to path. if key exists, - return key, with. - NOTE: 'struct stat' stat()ed from DB file is used as a container for 'struct stat' - of the regular file. st_ino, st_size, st_blocks are updated with file's values. - -readv() - - 1> do a lookup in bctx cache. if successful, return the requested data from cache. - 2> if cache missed, do a DB->get() the entire file content and insert to cache. - -writev(): - 1> flush any cached content of this file. - 2> do a DB->put(), with DB_DBT_PARTIAL flag. - NOTE: DB_DBT_PARTIAL is used to do partial update of a value in DB. - -readdir(): - 1> regular readdir() in a loop, and vomit all DB_ENV log files and DB files that - we encounter. - 2> if the readdir() buffer still has space, open a DB cursor and do a sequential - DBC->get() to fill the reaadir buffer. - - diff --git a/doc/hacker-guide/call-stub.txt b/doc/hacker-guide/call-stub.txt deleted file mode 100644 index bca1579b22d..00000000000 --- a/doc/hacker-guide/call-stub.txt +++ /dev/null @@ -1,1033 +0,0 @@ -creating a call stub and pausing a call ---------------------------------------- -libglusterfs provides seperate API to pause each of the fop. parameters to each API is -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). - NOTE: @fn should exactly take the same type and number of parameters that - the corresponding regular fop takes. -rest will be the regular parameters to corresponding fop. - -NOTE: @frame can never be NULL. fop_<operation>_stub() fails with errno - set to EINVAL, if @frame is NULL. also wherever @loc is applicable, - @loc cannot be NULL. - -refer to individual stub creation API to know about call-stub creation's behaviour with -specific parameters. - -here is the list of stub creation APIs for xlator fops. - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@need_xattr - flag to specify if xattr should be returned or not. -call_stub_t * -fop_lookup_stub (call_frame_t *frame, - fop_lookup_t fn, - loc_t *loc, - int32_t need_xattr); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -call_stub_t * -fop_stat_stub (call_frame_t *frame, - fop_stat_t fn, - loc_t *loc); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -call_stub_t * -fop_fstat_stub (call_frame_t *frame, - fop_fstat_t fn, - fd_t *fd); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to @loc->inode and - @loc->parent, if not NULL. also @loc->path will be copied to a different location. -@mode - mode parameter to chmod. -call_stub_t * -fop_chmod_stub (call_frame_t *frame, - fop_chmod_t fn, - loc_t *loc, - mode_t mode); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@mode - mode parameter for fchmod fop. -call_stub_t * -fop_fchmod_stub (call_frame_t *frame, - fop_fchmod_t fn, - fd_t *fd, - mode_t mode); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to @loc->inode and - @loc->parent, if not NULL. also @loc->path will be copied to a different location. -@uid - uid parameter to chown. -@gid - gid parameter to chown. -call_stub_t * -fop_chown_stub (call_frame_t *frame, - fop_chown_t fn, - loc_t *loc, - uid_t uid, - gid_t gid); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@uid - uid parameter to fchown. -@gid - gid parameter to fchown. -call_stub_t * -fop_fchown_stub (call_frame_t *frame, - fop_fchown_t fn, - fd_t *fd, - uid_t uid, - gid_t gid); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location, if not NULL. -@off - offset parameter to truncate fop. -call_stub_t * -fop_truncate_stub (call_frame_t *frame, - fop_truncate_t fn, - loc_t *loc, - off_t off); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@off - offset parameter to ftruncate fop. -call_stub_t * -fop_ftruncate_stub (call_frame_t *frame, - fop_ftruncate_t fn, - fd_t *fd, - off_t off); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@tv - tv parameter to utimens fop. -call_stub_t * -fop_utimens_stub (call_frame_t *frame, - fop_utimens_t fn, - loc_t *loc, - struct timespec tv[2]); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@mask - mask parameter for access fop. -call_stub_t * -fop_access_stub (call_frame_t *frame, - fop_access_t fn, - loc_t *loc, - int32_t mask); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@size - size parameter to readlink fop. -call_stub_t * -fop_readlink_stub (call_frame_t *frame, - fop_readlink_t fn, - loc_t *loc, - size_t size); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@mode - mode parameter to mknod fop. -@rdev - rdev parameter to mknod fop. -call_stub_t * -fop_mknod_stub (call_frame_t *frame, - fop_mknod_t fn, - loc_t *loc, - mode_t mode, - dev_t rdev); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@mode - mode parameter to mkdir fop. -call_stub_t * -fop_mkdir_stub (call_frame_t *frame, - fop_mkdir_t fn, - loc_t *loc, - mode_t mode); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -call_stub_t * -fop_unlink_stub (call_frame_t *frame, - fop_unlink_t fn, - loc_t *loc); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -call_stub_t * -fop_rmdir_stub (call_frame_t *frame, - fop_rmdir_t fn, - loc_t *loc); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@linkname - linkname parameter to symlink fop. -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -call_stub_t * -fop_symlink_stub (call_frame_t *frame, - fop_symlink_t fn, - const char *linkname, - loc_t *loc); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@oldloc - pointer to location structure. - NOTE: @oldloc will be copied to a different location, with inode_ref() to - @oldloc->inode and @oldloc->parent, if not NULL. also @oldloc->path will - be copied to a different location, if not NULL. -@newloc - pointer to location structure. - NOTE: @newloc will be copied to a different location, with inode_ref() to - @newloc->inode and @newloc->parent, if not NULL. also @newloc->path will - be copied to a different location, if not NULL. -call_stub_t * -fop_rename_stub (call_frame_t *frame, - fop_rename_t fn, - loc_t *oldloc, - loc_t *newloc); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@newpath - newpath parameter to link fop. -call_stub_t * -fop_link_stub (call_frame_t *frame, - fop_link_t fn, - loc_t *oldloc, - const char *newpath); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@flags - flags parameter to create fop. -@mode - mode parameter to create fop. -@fd - file descriptor parameter to create fop. - NOTE: @fd is stored with a fd_ref(). -call_stub_t * -fop_create_stub (call_frame_t *frame, - fop_create_t fn, - loc_t *loc, - int32_t flags, - mode_t mode, fd_t *fd); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@flags - flags parameter to open fop. -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -call_stub_t * -fop_open_stub (call_frame_t *frame, - fop_open_t fn, - loc_t *loc, - int32_t flags, - fd_t *fd); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@size - size parameter to readv fop. -@off - offset parameter to readv fop. -call_stub_t * -fop_readv_stub (call_frame_t *frame, - fop_readv_t fn, - fd_t *fd, - size_t size, - off_t off); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@vector - vector parameter to writev fop. - NOTE: @vector is iov_dup()ed while creating stub. and frame->root->req_refs - dictionary is dict_ref()ed. -@count - count parameter to writev fop. -@off - off parameter to writev fop. -call_stub_t * -fop_writev_stub (call_frame_t *frame, - fop_writev_t fn, - fd_t *fd, - struct iovec *vector, - int32_t count, - off_t off); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to flush fop. - NOTE: @fd is stored with a fd_ref(). -call_stub_t * -fop_flush_stub (call_frame_t *frame, - fop_flush_t fn, - fd_t *fd); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@datasync - datasync parameter to fsync fop. -call_stub_t * -fop_fsync_stub (call_frame_t *frame, - fop_fsync_t fn, - fd_t *fd, - int32_t datasync); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to @loc->inode and - @loc->parent, if not NULL. also @loc->path will be copied to a different location. -@fd - file descriptor parameter to opendir fop. - NOTE: @fd is stored with a fd_ref(). -call_stub_t * -fop_opendir_stub (call_frame_t *frame, - fop_opendir_t fn, - loc_t *loc, - fd_t *fd); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to getdents fop. - NOTE: @fd is stored with a fd_ref(). -@size - size parameter to getdents fop. -@off - off parameter to getdents fop. -@flags - flags parameter to getdents fop. -call_stub_t * -fop_getdents_stub (call_frame_t *frame, - fop_getdents_t fn, - fd_t *fd, - size_t size, - off_t off, - int32_t flag); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to setdents fop. - NOTE: @fd is stored with a fd_ref(). -@flags - flags parameter to setdents fop. -@entries - entries parameter to setdents fop. -call_stub_t * -fop_setdents_stub (call_frame_t *frame, - fop_setdents_t fn, - fd_t *fd, - int32_t flags, - dir_entry_t *entries, - int32_t count); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to setdents fop. - NOTE: @fd is stored with a fd_ref(). -@datasync - datasync parameter to fsyncdir fop. -call_stub_t * -fop_fsyncdir_stub (call_frame_t *frame, - fop_fsyncdir_t fn, - fd_t *fd, - int32_t datasync); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -call_stub_t * -fop_statfs_stub (call_frame_t *frame, - fop_statfs_t fn, - loc_t *loc); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@dict - dict parameter to setxattr fop. - NOTE: stub creation procedure stores @dict pointer with dict_ref() to it. -call_stub_t * -fop_setxattr_stub (call_frame_t *frame, - fop_setxattr_t fn, - loc_t *loc, - dict_t *dict, - int32_t flags); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@name - name parameter to getxattr fop. -call_stub_t * -fop_getxattr_stub (call_frame_t *frame, - fop_getxattr_t fn, - loc_t *loc, - const char *name); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@name - name parameter to removexattr fop. - NOTE: name string will be copied to a different location while creating stub. -call_stub_t * -fop_removexattr_stub (call_frame_t *frame, - fop_removexattr_t fn, - loc_t *loc, - const char *name); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to lk fop. - NOTE: @fd is stored with a fd_ref(). -@cmd - command parameter to lk fop. -@lock - lock parameter to lk fop. - NOTE: lock will be copied to a different location while creating stub. -call_stub_t * -fop_lk_stub (call_frame_t *frame, - fop_lk_t fn, - fd_t *fd, - int32_t cmd, - struct flock *lock); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - fd parameter to gf_lk fop. - NOTE: @fd is fd_ref()ed while creating stub, if not NULL. -@cmd - cmd parameter to gf_lk fop. -@lock - lock paramater to gf_lk fop. - NOTE: @lock is copied to a different memory location while creating - stub. -call_stub_t * -fop_gf_lk_stub (call_frame_t *frame, - fop_gf_lk_t fn, - fd_t *fd, - int32_t cmd, - struct flock *lock); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@fd - file descriptor parameter to readdir fop. - NOTE: @fd is stored with a fd_ref(). -@size - size parameter to readdir fop. -@off - offset parameter to readdir fop. -call_stub_t * -fop_readdir_stub (call_frame_t *frame, - fop_readdir_t fn, - fd_t *fd, - size_t size, - off_t off); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@loc - pointer to location structure. - NOTE: @loc will be copied to a different location, with inode_ref() to - @loc->inode and @loc->parent, if not NULL. also @loc->path will be - copied to a different location. -@flags - flags parameter to checksum fop. -call_stub_t * -fop_checksum_stub (call_frame_t *frame, - fop_checksum_t fn, - loc_t *loc, - int32_t flags); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@inode - inode parameter to @fn. - NOTE: @inode pointer is stored with a inode_ref(). -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -@dict - dict parameter to @fn. - NOTE: @dict pointer is stored with dict_ref(). -call_stub_t * -fop_lookup_cbk_stub (call_frame_t *frame, - fop_lookup_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *buf, - dict_t *dict); -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_stat_cbk_stub (call_frame_t *frame, - fop_stat_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_fstat_cbk_stub (call_frame_t *frame, - fop_fstat_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_chmod_cbk_stub (call_frame_t *frame, - fop_chmod_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_fchmod_cbk_stub (call_frame_t *frame, - fop_fchmod_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_chown_cbk_stub (call_frame_t *frame, - fop_chown_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_fchown_cbk_stub (call_frame_t *frame, - fop_fchown_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_truncate_cbk_stub (call_frame_t *frame, - fop_truncate_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_ftruncate_cbk_stub (call_frame_t *frame, - fop_ftruncate_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_utimens_cbk_stub (call_frame_t *frame, - fop_utimens_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_access_cbk_stub (call_frame_t *frame, - fop_access_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@path - path parameter to @fn. - NOTE: @path is copied to a different memory location, if not NULL. -call_stub_t * -fop_readlink_cbk_stub (call_frame_t *frame, - fop_readlink_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - const char *path); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@inode - inode parameter to @fn. - NOTE: @inode pointer is stored with a inode_ref(). -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_mknod_cbk_stub (call_frame_t *frame, - fop_mknod_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@inode - inode parameter to @fn. - NOTE: @inode pointer is stored with a inode_ref(). -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_mkdir_cbk_stub (call_frame_t *frame, - fop_mkdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_unlink_cbk_stub (call_frame_t *frame, - fop_unlink_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_rmdir_cbk_stub (call_frame_t *frame, - fop_rmdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@inode - inode parameter to @fn. - NOTE: @inode pointer is stored with a inode_ref(). -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_symlink_cbk_stub (call_frame_t *frame, - fop_symlink_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_rename_cbk_stub (call_frame_t *frame, - fop_rename_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@inode - inode parameter to @fn. - NOTE: @inode pointer is stored with a inode_ref(). -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_link_cbk_stub (call_frame_t *frame, - fop_link_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct stat *buf); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@fd - fd parameter to @fn. - NOTE: @fd pointer is stored with a fd_ref(). -@inode - inode parameter to @fn. - NOTE: @inode pointer is stored with a inode_ref(). -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_create_cbk_stub (call_frame_t *frame, - fop_create_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - inode_t *inode, - struct stat *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@fd - fd parameter to @fn. - NOTE: @fd pointer is stored with a fd_ref(). -call_stub_t * -fop_open_cbk_stub (call_frame_t *frame, - fop_open_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - fd_t *fd); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@vector - vector parameter to @fn. - NOTE: @vector is copied to a different memory location, if not NULL. also - frame->root->rsp_refs is dict_ref()ed. -@stbuf - stbuf parameter to @fn. - NOTE: @stbuf is copied to a different memory location, if not NULL. -call_stub_t * -fop_readv_cbk_stub (call_frame_t *frame, - fop_readv_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct iovec *vector, - int32_t count, - struct stat *stbuf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@stbuf - stbuf parameter to @fn. - NOTE: @stbuf is copied to a different memory location, if not NULL. -call_stub_t * -fop_writev_cbk_stub (call_frame_t *frame, - fop_writev_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *stbuf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_flush_cbk_stub (call_frame_t *frame, - fop_flush_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_fsync_cbk_stub (call_frame_t *frame, - fop_fsync_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@fd - fd parameter to @fn. - NOTE: @fd pointer is stored with a fd_ref(). -call_stub_t * -fop_opendir_cbk_stub (call_frame_t *frame, - fop_opendir_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - fd_t *fd); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@entries - entries parameter to @fn. -@count - count parameter to @fn. -call_stub_t * -fop_getdents_cbk_stub (call_frame_t *frame, - fop_getdents_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - dir_entry_t *entries, - int32_t count); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_setdents_cbk_stub (call_frame_t *frame, - fop_setdents_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_fsyncdir_cbk_stub (call_frame_t *frame, - fop_fsyncdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@buf - buf parameter to @fn. - NOTE: @buf is copied to a different memory location, if not NULL. -call_stub_t * -fop_statfs_cbk_stub (call_frame_t *frame, - fop_statfs_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct statvfs *buf); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_setxattr_cbk_stub (call_frame_t *frame, - fop_setxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@value - value dictionary parameter to @fn. - NOTE: @value pointer is stored with a dict_ref(). -call_stub_t * -fop_getxattr_cbk_stub (call_frame_t *frame, - fop_getxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - dict_t *value); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -call_stub_t * -fop_removexattr_cbk_stub (call_frame_t *frame, - fop_removexattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@lock - lock parameter to @fn. - NOTE: @lock is copied to a different memory location while creating - stub. -call_stub_t * -fop_lk_cbk_stub (call_frame_t *frame, - fop_lk_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct flock *lock); - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@lock - lock parameter to @fn. - NOTE: @lock is copied to a different memory location while creating - stub. -call_stub_t * -fop_gf_lk_cbk_stub (call_frame_t *frame, - fop_gf_lk_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct flock *lock); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@entries - entries parameter to @fn. -call_stub_t * -fop_readdir_cbk_stub (call_frame_t *frame, - fop_readdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries); - - -@frame - call frame which has to be used to resume the call at call_resume(). -@fn - procedure to call during call_resume(). -@op_ret - op_ret parameter to @fn. -@op_errno - op_errno parameter to @fn. -@file_checksum - file_checksum parameter to @fn. - NOTE: file_checksum will be copied to a different memory location - while creating stub. -@dir_checksum - dir_checksum parameter to @fn. - NOTE: file_checksum will be copied to a different memory location - while creating stub. -call_stub_t * -fop_checksum_cbk_stub (call_frame_t *frame, - fop_checksum_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - uint8_t *file_checksum, - uint8_t *dir_checksum); - -resuming a call: ---------------- - call can be resumed using call stub through call_resume API. - - void call_resume (call_stub_t *stub); - - stub - call stub created during pausing a call. - - NOTE: call_resume() will decrease reference count of any fd_t, dict_t and inode_t that it finds - in stub->args.<operation>.<fd_t-or-inode_t-or-dict_t>. so, if any fd_t, dict_t or - inode_t pointers are assigned at stub->args.<operation>.<fd_t-or-inode_t-or-dict_t> after - fop_<operation>_stub() call, they must be <fd_t-or-inode_t-or-dict_t>_ref()ed. - - call_resume does not STACK_DESTROY() for any fop. - - if stub->fn is NULL, call_resume does STACK_WIND() or STACK_UNWIND() using the stub->frame. - - return - call resume fails only if stub is NULL. call resume fails with errno set to EINVAL. diff --git a/doc/hacker-guide/hacker-guide.tex b/doc/hacker-guide/hacker-guide.tex deleted file mode 100644 index c2d7255d7df..00000000000 --- a/doc/hacker-guide/hacker-guide.tex +++ /dev/null @@ -1,309 +0,0 @@ -\documentclass{book}[12pt] -\usepackage{graphicx} -% \usepackage{fancyhdr} - -% \pagestyle{fancy} -\begin{document} - -% \headheight 117pt -% \rhead{\includegraphics{zr-logo.eps}} - -\author{Gluster} -\title{GlusterFS 1.3 Hacker's Guide} -\date{June 1, 2007} - -\maketitle -\frontmatter -\tableofcontents - -\mainmatter -\chapter{Introduction} - -\section{Coding guidelines} -GlusterFS uses Git for version control. To get the latest source do: -\begin{verbatim} - $ git clone git://git.gluster.com/glusterfs.git glusterfs -\end{verbatim} -\noindent -GlusterFS follows the GNU coding -standards\footnote{http://www.gnu.org/prep/standards\_toc.html} for the -most part. - -\chapter{Major components} -\section{libglusterfs} -\texttt{libglusterfs} contains supporting code used by all the other components. -The important files here are: - -\texttt{dict.c}: This is an implementation of a serializable dictionary type. It is -used by the protocol code to send requests and replies. It is also used to pass options -to translators. - -\texttt{logging.c}: This is a thread-safe logging library. The log messages go to a -file (default \texttt{/usr/local/var/log/glusterfs/*}). - -\texttt{protocol.c}: This file implements the GlusterFS on-the-wire -protocol. The protocol itself is a simple ASCII protocol, designed to -be easy to parse and be human readable. - -A sample GlusterFS protocol block looks like this: -\begin{verbatim} - Block Start header - 0000000000000023 callid - 00000001 type - 00000016 op - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx human-readable name - 00000000000000000000000000000ac3 block size - <...> block - Block End -\end{verbatim} - -\texttt{stack.h}: This file defines the \texttt{STACK\_WIND} and -\texttt{STACK\_UNWIND} macros which are used to implement the parallel -stack that is maintained for inter-xlator calls. See the \textsl{Taking control -of the stack} section below for more details. - -\texttt{spec.y}: This contains the Yacc grammar for the GlusterFS -specification file, and the parsing code. - - -Draw diagrams of trees -Two rules: -(1) directory structure is same -(2) file can exist only on one node - -\section{glusterfs-fuse} -\section{glusterfsd} -\section{transport} -\section{scheduler} -\section{xlator} - -\chapter{xlators} -\section{Taking control of the stack} -One can think of STACK\_WIND/UNWIND as a very specific RPC mechanism. - -% \includegraphics{stack.eps} - -\section{Overview of xlators} - -\flushleft{\LARGE\texttt{cluster/}} -\vskip 2ex -\flushleft{\Large\texttt{afr}} -\vskip 2ex -\flushleft{\Large\texttt{stripe}} -\vskip 2ex -\flushleft{\Large\texttt{unify}} - -\vskip 4ex -\flushleft{\LARGE\texttt{debug/}} -\vskip 2ex -\flushleft{\Large\texttt{trace}} -\vskip 2ex -The trace xlator simply logs all fops and mops, and passes them through to its child. - -\vskip 4ex -\flushleft{\LARGE\texttt{features/}} -\flushleft{\Large\texttt{posix-locks}} -\vskip 2ex -This xlator implements \textsc{posix} record locking semantics over -any kind of storage. - -\vskip 4ex -\flushleft{\LARGE\texttt{performance/}} - -\flushleft{\Large\texttt{io-threads}} -\vskip 2ex -\flushleft{\Large\texttt{read-ahead}} -\vskip 2ex -\flushleft{\Large\texttt{stat-prefetch}} -\vskip 2ex -\flushleft{\Large\texttt{write-behind}} -\vskip 2ex - -\vskip 4ex -\flushleft{\LARGE\texttt{protocol/}} -\vskip 2ex - -\flushleft{\Large\texttt{client}} -\vskip 2ex - -\flushleft{\Large\texttt{server}} -\vskip 2ex - -\vskip 4ex -\flushleft{\LARGE\texttt{storage/}} -\flushleft{\Large\texttt{posix}} -\vskip 2ex -The \texttt{posix} xlator is the one which actually makes calls to the -on-disk filesystem. Currently this is the only storage xlator available. However, -plans to develop other storage xlators, such as one for Amazon's S3 service, are -on the roadmap. - -\chapter{Writing a simple xlator} -\noindent -In this section we're going to write a rot13 xlator. ``Rot13'' is a -simple substitution cipher which obscures a text by replacing each -letter with the letter thirteen places down the alphabet. So `a' (0) -would become `n' (12), `b' would be 'm', and so on. Rot13 applied to -a piece of ciphertext yields the plaintext again, because rot13 is its -own inverse, since: - -\[ -x_c = x + 13\; (mod\; 26) -\] -\[ -x_c + 13\; (mod\; 26) = x + 13 + 13\; (mod\; 26) = x -\] - -First we include the requisite headers. - -\begin{verbatim} -#include <ctype.h> -#include <sys/uio.h> - -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" - -/* - * This is a rot13 ``encryption'' xlator. It rot13's data when - * writing to disk and rot13's it back when reading it. - * This xlator is meant as an example, not for production - * use ;) (hence no error-checking) - */ - -\end{verbatim} - -Then we write the rot13 function itself. For simplicity, we only transform lower case -letters. Any other byte is passed through as it is. - -\begin{verbatim} -/* We only handle lower case letters for simplicity */ -static void -rot13 (char *buf, int len) -{ - int i; - for (i = 0; i < len; i++) { - if (isalpha (buf[i])) - buf[i] = (buf[i] - 'a' + 13) % 26; - else if (buf[i] <= 26) - buf[i] = (buf[i] + 13) % 26 + 'a'; - } -} -\end{verbatim} - -Next comes a utility function whose purpose will be clear after looking at the code -below. - -\begin{verbatim} -static void -rot13_iovec (struct iovec *vector, int count) -{ - int i; - for (i = 0; i < count; i++) { - rot13 (vector[i].iov_base, vector[i].iov_len); - } -} -\end{verbatim} - -\begin{verbatim} -static int32_t -rot13_readv_cbk (call_frame_t *frame, - call_frame_t *prev_frame, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct iovec *vector, - int32_t count) -{ - rot13_iovec (vector, count); - - STACK_UNWIND (frame, op_ret, op_errno, vector, count); - return 0; -} - -static int32_t -rot13_readv (call_frame_t *frame, - xlator_t *this, - dict_t *ctx, - size_t size, - off_t offset) -{ - STACK_WIND (frame, - rot13_readv_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->readv, - ctx, size, offset); - return 0; -} - -static int32_t -rot13_writev_cbk (call_frame_t *frame, - call_frame_t *prev_frame, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) -{ - STACK_UNWIND (frame, op_ret, op_errno); - return 0; -} - -static int32_t -rot13_writev (call_frame_t *frame, - xlator_t *this, - dict_t *ctx, - struct iovec *vector, - int32_t count, - off_t offset) -{ - rot13_iovec (vector, count); - - STACK_WIND (frame, - rot13_writev_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->writev, - ctx, vector, count, offset); - return 0; -} - -\end{verbatim} - -Every xlator must define two functions and two external symbols. The functions are -\texttt{init} and \texttt{fini}, and the symbols are \texttt{fops} and \texttt{mops}. -The \texttt{init} function is called when the xlator is loaded by GlusterFS, and -contains code for the xlator to initialize itself. Note that if an xlator is present -multiple times in the spec tree, the \texttt{init} function will be called each time -the xlator is loaded. - -\begin{verbatim} -int32_t -init (xlator_t *this) -{ - if (!this->children) { - gf_log ("rot13", GF_LOG_ERROR, - "FATAL: rot13 should have exactly one child"); - return -1; - } - - gf_log ("rot13", GF_LOG_DEBUG, "rot13 xlator loaded"); - return 0; -} -\end{verbatim} - -\begin{verbatim} - -void -fini (xlator_t *this) -{ - return; -} - -struct xlator_fops fops = { - .readv = rot13_readv, - .writev = rot13_writev -}; - - -\end{verbatim} - -\end{document} - diff --git a/doc/hacker-guide/lock-ahead.txt b/doc/hacker-guide/lock-ahead.txt deleted file mode 100644 index 63392b7fa2c..00000000000 --- a/doc/hacker-guide/lock-ahead.txt +++ /dev/null @@ -1,80 +0,0 @@ - Lock-ahead translator - --------------------- - -The objective of the lock-ahead translator is to speculatively -hold locks (inodelk and entrylk) on the universal set (0 - infinity -in case of inodelk and all basenames in case of entrylk) even -when a lock is requested only on a subset, in anticipation that -further locks will be requested within the same universal set. - -So, for example, when cluster/replicate locks a region before -writing to it, lock-ahead would instead lock the entire file. -On further writes, lock-ahead can immediately return success for -the lock requests, since the entire file has been previously locked. - -To avoid starvation of other clients/mountpoints, we employ a -notify mechanism, described below. - -typedef struct { - struct list_head subset_locks; -} la_universal_lock_t; - -Universal lock structure is stored in the inode context. - -typedef struct { - enum {LOCK_AHEAD_ENTRYLK, LOCK_AHEAD_FENTRYLK, - LOCK_AHEAD_INODELK, LOCK_AHEAD_FINODELK}; - - union { - fd_t *fd; - loc_t loc; - }; - - off_t l_start; - off_t l_len; - - const char *basename; - - struct list_head universal_lock; -} la_subset_lock_t; - - -fops implemented: - -* inodelk/finodelk/entrylk/fentrylk: - -lock: - if universal lock held: - add subset to it (save loc_t or fd) and return success - else: - send lock-notify fop - hold universal lock and return - (set inode context, add subset to it, save loc_t or fd) - - if this fails: - forward the lock request - -unlock: - if subset exists in universal lock: - delete subset lock from list - else: - forward it - -* release: - hold subset locks (each subset lock using the saved loc_t or fd) - and release universal lock - -* lock-notify (on unwind) (new fop) - hold subset locks and release universal lock - - -lock-notify in locks translator: - -if a subset lock in entrylk/inodelk cannot be satisfied -because of a universal lock held by someone else: - unwind the lock-notify fop - -============================================== -$ Last updated: Tue Feb 17 11:31:18 IST 2009 $ -$ Author: Vikas Gorur <vikas@gluster.com> $ -============================================== diff --git a/doc/hacker-guide/posix.txt b/doc/hacker-guide/posix.txt deleted file mode 100644 index d0132abfedc..00000000000 --- a/doc/hacker-guide/posix.txt +++ /dev/null @@ -1,59 +0,0 @@ ---------------- -* storage/posix ---------------- - -- SET_FS_ID - - This is so that all filesystem checks are done with the user's - uid/gid and not GlusterFS's uid/gid. - -- MAKE_REAL_PATH - - This macro concatenates the base directory of the posix volume - ('option directory') with the given path. - -- need_xattr in lookup - - If this flag is passed, lookup returns a xattr dictionary that contains - the file's create time, the file's contents, and the version number - of the file. - - This is a hack to increase small file performance. If an application - wants to read a small file, it can finish its job with just a lookup - call instead of a lookup followed by read. - -- getdents/setdents - - These are used by unify to set and get directory entries. - -- ALIGN_BUF - - Macro to align an address to a page boundary (4K). - -- priv->export_statfs - - In some cases, two exported volumes may reside on the same - partition on the server. Sending statvfs info for both - the volumes will lead to erroneous df output at the client, - since free space on the partition will be counted twice. - - In such cases, user can disable exporting statvfs info - on one of the volumes by setting this option. - -- xattrop - - This fop is used by replicate to set version numbers on files. - -- getxattr/setxattr hack to read/write files - - A key, GLUSTERFS_FILE_CONTENT_STRING, is handled in a special way by - getxattr/setxattr. A getxattr with the key will return the entire - content of the file as the value. A setxattr with the key will write - the value as the entire content of the file. - -- posix_checksum - - This calculates a simple XOR checksum on all entry names in a - directory that is used by unify to compare directory contents. - - diff --git a/doc/hacker-guide/replicate.txt b/doc/hacker-guide/replicate.txt deleted file mode 100644 index fd1ef2747f0..00000000000 --- a/doc/hacker-guide/replicate.txt +++ /dev/null @@ -1,206 +0,0 @@ ---------------- -* cluster/replicate ---------------- - -Before understanding replicate, one must understand two internal FOPs: - -GF_FILE_LK: - This is exactly like fcntl(2) locking, except the locks are in a - separate domain from locks held by applications. - -GF_DIR_LK (loc_t *loc, char *basename): - This allows one to lock a name under a directory. For example, - to lock /mnt/glusterfs/foo, one would use the call: - - GF_DIR_LK ({loc_t for "/mnt/glusterfs"}, "foo") - - If one wishes to lock *all* the names under a particular directory, - supply the basename argument as NULL. - - The locks can either be read locks or write locks; consult the - function prototype for more details. - -Both these operations are implemented by the features/locks (earlier -known as posix-locks) translator. - --------------- -* Basic design --------------- - -All FOPs can be classified into four major groups: - - - inode-read - Operations that read an inode's data (file contents) or metadata (perms, etc.). - - access, getxattr, fstat, readlink, readv, stat. - - - inode-write - Operations that modify an inode's data or metadata. - - chmod, chown, truncate, writev, utimens. - - - dir-read - Operations that read a directory's contents or metadata. - - readdir, getdents, checksum. - - - dir-write - Operations that modify a directory's contents or metadata. - - create, link, mkdir, mknod, rename, rmdir, symlink, unlink. - - Some of these make a subgroup in that they modify *two* different entries: - link, rename, symlink. - - - Others - Other operations. - - flush, lookup, open, opendir, statfs. - ------------- -* Algorithms ------------- - -Each of the four major groups has its own algorithm: - - ---------------------- - - inode-read, dir-read - ---------------------- - - = Send a request to the first child that is up: - - if it fails: - try the next available child - - if we have exhausted all children: - return failure - - ------------- - - inode-write - ------------- - - All operations are done in parallel unless specified otherwise. - - (1) Send a GF_FILE_LK request on all children for a write lock on - the appropriate region - (for metadata operations: entire file (0, 0) - for writev: (offset, offset+size of buffer)) - - - If a lock request fails on a child: - unlock all children - try to acquire a blocking lock (F_SETLKW) on each child, serially. - - If this fails (due to ENOTCONN or EINVAL): - Consider this child as dead for rest of transaction. - - (2) Mark all children as "pending" on all (alive) children - (see below for meaning of "pending"). - - - If it fails on any child: - mark it as dead (in transaction local state). - - (3) Perform operation on all (alive) children. - - - If it fails on any child: - mark it as dead (in transaction local state). - - (4) Unmark all successful children as not "pending" on all nodes. - - (5) Unlock region on all (alive) children. - - ----------- - - dir-write - ----------- - - The algorithm for dir-write is same as above except instead of holding - GF_FILE_LK locks we hold a GF_DIR_LK lock on the name being operated upon. - In case of link-type calls, we hold locks on both the operand names. - ------------ -* "pending" ------------ - - The "pending" number is like a journal entry. A pending entry is an - array of 32-bit integers stored in network byte-order as the extended - attribute of an inode (which can be a directory as well). - - There are three keys corresponding to three types of pending operations: - - - AFR_METADATA_PENDING - There are some metadata operations pending on this inode (perms, ctime/mtime, - xattr, etc.). - - - AFR_DATA_PENDING - There is some data pending on this inode (writev). - - - AFR_ENTRY_PENDING - There are some directory operations pending on this directory - (create, unlink, etc.). - ------------ -* Self heal ------------ - - - On lookup, gather extended attribute data: - - If entry is a regular file: - - If an entry is present on one child and not on others: - - create entry on others. - - If entries exist but have different metadata (perms, etc.): - - consider the entry with the highest AFR_METADATA_PENDING number as - definitive and replicate its attributes on children. - - - If entry is a directory: - - Consider the entry with the higest AFR_ENTRY_PENDING number as - definitive and replicate its contents on all children. - - - If any two entries have non-matching types (i.e., one is file and - other is directory): - - Announce to the user via log that a split-brain situation has been - detected, and do nothing. - - - On open, gather extended attribute data: - - Consider the file with the highest AFR_DATA_PENDING number as - the definitive one and replicate its contents on all other - children. - - During all self heal operations, appropriate locks must be held on all - regions/entries being affected. - ---------------- -* Inode scaling ---------------- - -Inode scaling is necessary because if a situation arises where: - - An inode number is returned for a directory (by lookup) which was - previously the inode number of a file (as per FUSE's table), then - FUSE gets horribly confused (consult a FUSE expert for more details). - -To avoid such a situation, we distribute the 64-bit inode space equally -among all children of replicate. - -To illustrate: - -If c1, c2, c3 are children of replicate, they each get 1/3 of the available -inode space: - -Child: c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 ... -Inode number: 1 2 3 4 5 6 7 8 9 10 11 ... - -Thus, if lookup on c1 returns an inode number "2", it is scaled to "4" -(which is the second inode number in c1's space). - -This way we ensure that there is never a collision of inode numbers from -two different children. - -This reduction of inode space doesn't really reduce the usability of -replicate since even if we assume replicate has 1024 children (which would be a -highly unusual scenario), each child still has a 54-bit inode space. - -2^54 ~ 1.8 * 10^16 - -which is much larger than any real world requirement. - - -============================================== -$ Last updated: Sun Oct 12 23:17:01 IST 2008 $ -$ Author: Vikas Gorur <vikas@gluster.com> $ -============================================== - diff --git a/doc/hacker-guide/write-behind.txt b/doc/hacker-guide/write-behind.txt deleted file mode 100644 index 498e95480ae..00000000000 --- a/doc/hacker-guide/write-behind.txt +++ /dev/null @@ -1,45 +0,0 @@ -basic working --------------- - - write behind is basically a translator to lie to the application that the write-requests are finished, even before it is actually finished. - - on a regular translator tree without write-behind, control flow is like this: - - 1. application makes a write() system call. - 2. VFS ==> FUSE ==> /dev/fuse. - 3. fuse-bridge initiates a glusterfs writev() call. - 4. writev() is STACK_WIND()ed upto client-protocol or storage translator. - 5. client-protocol, on recieving reply from server, starts STACK_UNWIND() towards the fuse-bridge. - - on a translator tree with write-behind, control flow is like this: - - 1. application makes a write() system call. - 2. VFS ==> FUSE ==> /dev/fuse. - 3. fuse-bridge initiates a glusterfs writev() call. - 4. writev() is STACK_WIND()ed upto write-behind translator. - 5. write-behind adds the write buffer to its internal queue and does a STACK_UNWIND() towards the fuse-bridge. - - write call is completed in application's percepective. after STACK_UNWIND()ing towards the fuse-bridge, write-behind initiates a fresh writev() call to its child translator, whose replies will be consumed by write-behind itself. write-behind _doesn't_ cache the write buffer, unless 'option flush-behind on' is specified in volume specification file. - -windowing ---------- - - write respect to write-behind, each write-buffer has three flags: 'stack_wound', 'write_behind' and 'got_reply'. - - stack_wound: if set, indicates that write-behind has initiated STACK_WIND() towards child translator. - - write_behind: if set, indicates that write-behind has done STACK_UNWIND() towards fuse-bridge. - - got_reply: if set, indicates that write-behind has recieved reply from child translator for a writev() STACK_WIND(). a request will be destroyed by write-behind only if this flag is set. - - currently pending write requests = aggregate size of requests with write_behind = 1 and got_reply = 0. - - window size limits the aggregate size of currently pending write requests. once the pending requests' size has reached the window size, write-behind blocks writev() calls from fuse-bridge. - blocking is only from application's perspective. write-behind does STACK_WIND() to child translator straight-away, but hold behind the STACK_UNWIND() towards fuse-bridge. STACK_UNWIND() is done only once write-behind gets enough replies to accomodate for currently blocked request. - -flush behind ------------- - - if 'option flush-behind on' is specified in volume specification file, then write-behind sends aggregate write requests to child translator, instead of regular per request STACK_WIND()s. - - diff --git a/doc/handling-options.txt b/doc/handling-options.txt deleted file mode 100644 index cac1fe93947..00000000000 --- a/doc/handling-options.txt +++ /dev/null @@ -1,13 +0,0 @@ - -How to add a new option to a given volume ? -=========================================== - -* Add a entry in 'struct volume_options options[]' with your key, what is - the type of the 'key', etc. - -* The 'key' and corresponding 'value' given for the same by user are validated - before calling init() of the translator/transport/scheduler/auth-module. - -* Once the complete init() is successful, user will get a warning if he has - given a 'key' which is not defined in these modules. - diff --git a/doc/mac-related-xattrs.txt b/doc/mac-related-xattrs.txt deleted file mode 100644 index 805658334e6..00000000000 --- a/doc/mac-related-xattrs.txt +++ /dev/null @@ -1,21 +0,0 @@ - -This document is intended to briefly explain how the Extended Attributes on -Darwin 10.5.x releases works ----- - -On Darwin other than all the normal filesystem operations, 'Finder' (like -Explorer in Windows but a little more) keeps its information in two extended -attributes named 'com.apple.FinderInfo' and 'com.apple.ResourceFork'. If these -xattrs are not implemented the filesystem won't be shown on Finder, and if they -are not implemented properly there may be issues when some of the file operations -are done through GUI of Finder. But when a filesystem is used over mountpoint in a -terminal, everything is fine and these xattrs are not required. - -Currently the way these xattrs are implemented is simple. All the xattr calls -(getxattr, setxattr, listxattr, removexattr) are passed down to underlaying filesystem, -most of the cases when exported FS is on MacOS X itself, these keys are supported, hence -the fops succeed. But in the case of using exports of different OS on Darwin the issue is -extended attribute prefix like 'com.apple.' may not be supported, hence the problem with -Finder. To solve this issue, GlusterFS returns virtual default values to these keys, which -works fine on most of the cases. - diff --git a/doc/mount.glusterfs.8 b/doc/mount.glusterfs.8 index d4927e0a92f..ce16e9e40b7 100644 --- a/doc/mount.glusterfs.8 +++ b/doc/mount.glusterfs.8 @@ -1,37 +1,31 @@ -.\" Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com> +.\" Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com> .\" This file is part of GlusterFS. .\" -.\" GlusterFS is free software; you can redistribute it and/or modify -.\" it under the terms of the GNU Affero General Public License as published -.\" by the Free Software Foundation; either version 3 of the License, -.\" or (at your option) any later version. +.\" This file is licensed to you under your choice of the GNU Lesser +.\" General Public License, version 3 or any later version (LGPLv3 or +.\" later), or the GNU General Public License, version 2 (GPLv2), in all +.\" cases as published by the Free Software Foundation. .\" -.\" GlusterFS 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 -.\" Affero General Public License for more details. .\" -.\" You should have received a copy of the GNU Affero General Public License -.\" long with this program. If not, see -.\" <http://www.gnu.org/licenses/>. .\" -.\" -.\" -.TH GlusterFS 8 "Cluster Filesystem" "18 March 2010" "Gluster Inc." +.TH GlusterFS 8 "Cluster Filesystem" "14 September 2013" "Red Hat, Inc." .SH NAME -mount.glusterfs - script to mount native GlusterFS volume +.B mount.glusterfs - script to mount native GlusterFS volume .SH SYNOPSIS -.B mount -t glusterfs -.I [-o <options>] <volumeserver>:<volumeid> <mountpoint> +.B mount -t glusterfs [-o <options>] <volumeserver>:/<volume>[/<subdir>] +.B <mountpoint> +.TP +.B mount -t glusterfs [-o <options>] <server1>,<server2>, +.B <server3>,..<serverN>:/<volname>[/<subdir>] <mount_point> .TP -.B mount -t glusterfs -.I [-o <options>] <path/to/volumefile> <mountpoint> +.TP +.B mount -t glusterfs [-o <options>] <path/to/volumefile> <mountpoint> .PP .SH DESCRIPTION This tool is part of \fBglusterfs\fR(8) package, which is used to mount using GlusterFS native binary. -\fBmount.glusterfs\fR is meant to be used by the mount(8) command for mounting +\fBmount.glusterfs\fR is meant to be used by the mount(8) command for mounting native GlusterFS client. This subcommand, however, can also be used as a standalone command with limited functionality. @@ -45,43 +39,139 @@ File to use for logging [default:/var/log/glusterfs/glusterfs.log] .TP \fBlog\-level=\fRLOG-LEVEL Logging severity. Valid options are TRACE, DEBUG, WARNING, ERROR, CRITICAL -NORMAL and NONE [default: NORMAL] +INFO and NONE [default: INFO] +.TP +\fBacl +Mount the filesystem with POSIX ACL support +.TP +\fBfopen\-keep\-cache[=BOOL] +Do not purge the cache on file open (default: false) +.TP +\fBworm +Mount the filesystem in 'worm' mode +.TP +\fBaux\-gfid\-mount +Enable access to filesystem through gfid directly .TP \fBro\fR Mount the filesystem read-only +.TP +\fBenable\-ino32=\fRBOOL +Use 32-bit inodes when mounting to workaround broken applications that don't +support 64-bit inodes +.TP +\fBmem\-accounting +Enable internal memory accounting +.TP +\fBcapability +Enable file capability setting and retrival +.TP +\fBthin-client +Enables thin mount and connects via gfproxyd daemon + .PP .SS "Advanced options" .PP .TP -\fBvolfile\-id=\fRKEY -Volume key or name of the volume file to be fetched from server +\fBattribute\-timeout=\fRSECONDS +Set attribute timeout to SECONDS for inodes in fuse kernel module [default: 1] +.TP +\fBentry\-timeout=\fRSECONDS +Set entry timeout to SECONDS in fuse kernel module [default: 1] +.TP +\fBbackground\-qlen=\fRN +Set fuse module's background queue length to N [default: 64] .TP -\fBtransport=\fRTRANSPORT-TYPE -Transport type to get volume file from server [default: socket] +\fBgid\-timeout=\fRSECONDS +Set auxiliary group list timeout to SECONDS for fuse translator [default: 0] +.TP +\fBnegative\-timeout=\fRSECONDS +Set negative timeout to SECONDS in fuse kernel module [default: 0] .TP \fBvolume\-name=\fRVOLUME-NAME Volume name to be used for MOUNT-POINT [default: top most volume in VOLUME-FILE] .TP -\fBdirect\-io\-mode=\fRdisable -Disable direct I/O mode in fuse kernel module +\fBdirect\-io\-mode=\fRBOOL|auto +Specify fuse direct I/O strategy [default: auto] +.TP +\fBcongestion\-threshold=\fRN +Set fuse module's congestion threshold to N [default: 48] +.TP +\fsubdir\-mount=\fRN +Set the subdirectory mount option [default: NULL, ie, no subdirectory mount] +.TP +.TP +\fBbackup\-volfile\-servers=\fRSERVERLIST +Provide list of backup volfile servers in the following format [default: None] + +\fB$ mount \-t glusterfs \-obackup\-volfile\-servers=<server2>:\fR +\fB <server3>:...:<serverN> <server1>:/<volname> <mount_point>\fR + +.TP +.TP +\fBbackupvolfile\-server=\fRSERVER +Provide list of backup volfile servers in the following format [default: None] + +\fB $ mount \-t glusterfs \-obackupvolfile\-server=<server2> +\fB <server1>:/<volname> <mount_point> + +.TP +.TP +\fBfetch-attempts=\fRN +\fBDeprecated\fR option - placed here for backward compatibility [default: 1] +.TP +.TP +\fBlru-limit=\fRN +Set fuse module's limit for number of inodes kept in LRU list to N [default: 65536] +.TP +.TP +\fBinvalidate-limit=\fRN +Suspend fuse invalidations implied by 'lru-limit' if number of outstanding +invalidations reaches N +.TP +.TP +\fBbackground-qlen=\fRN +Set fuse module's background queue length to N [default: 64] +.TP +\fBno\-root\-squash=\fRBOOL +disable root squashing for the trusted client [default: off] +.TP +\fBroot\-squash=\fRBOOL +enable root squashing for the trusted client [default: on] +.TP +\fBuse\-readdirp=\fRBOOL +Use readdirp() mode in fuse kernel module [default: on] +.TP +\fBdump\-fuse=\fRPATH +Dump fuse traffic to PATH +.TP +\fBkernel\-writeback\-cache=\fRBOOL +Enable fuse in-kernel writeback cache [default: off] +.TP +\fBattr\-times\-granularity=\fRNS +Declare supported granularity of file attribute [default: 0] .TP +\fBauto\-invalidation=\fRBOOL +controls whether fuse-kernel can auto-invalidate attribute, dentry and +page-cache. Disable this only if same files/directories are not +accessed across two different mounts concurrently [default: on] .PP .SH FILES .TP .I /etc/fstab A typical GlusterFS entry in /etc/fstab looks like below -server1.gluster.com:mirror /mnt/mirror glusterfs log-file=/var/log/mirror.vol,ro,defaults 0 0 +\fBserver1:/mirror /mnt/mirror glusterfs log-file=/var/log/mirror.log,acl 0 0\fR .TP -.I /etc/mtab -An example entry of a GlusterFS mountpoint in /etc/mtab looks like below +.I /proc/mounts +An example entry of a GlusterFS mountpoint in /proc/mounts looks like below -mirror.vol /mnt/glusterfs fuse.glusterfs rw,allow_other,default_permissions,max_read=131072 0 0 +\fBserver1:/mirror /mnt/glusterfs fuse.glusterfs rw,allow_other,default_permissions,max_read=131072 0 0\fR .SH SEE ALSO \fBglusterfs\fR(8), \fBmount\fR(8), \fBgluster\fR(8) .SH COPYRIGHT -Copyright(c) 2006-2011 Gluster, Inc. <http://www.gluster.com> +Copyright(c) 2006-2013 Red Hat, Inc. <http://www.redhat.com> diff --git a/doc/porting_guide.txt b/doc/porting_guide.txt deleted file mode 100644 index 905bb422858..00000000000 --- a/doc/porting_guide.txt +++ /dev/null @@ -1,45 +0,0 @@ - GlusterFS Porting Guide - ----------------------- - -* General setup - -The configure script will detect the target platform for the build. -All platform-specific CFLAGS, macro definitions should be done -in configure.ac - -Platform-specific code can be written like this: - -#ifdef GF_DARWIN_HOST_OS - /* some code specific to Darwin */ -#endif - -* Coding guidelines - -In general, avoid glibc extensions. For example, nested functions don't work -on Mac OS X. It is best to stick to C99. - -When using library calls and system calls, pay attention to the -portability notes. As far as possible stick to POSIX-specified behavior. -Do not use anything expressly permitted by the specification. For example, -some fields in structures may be present only on certain platforms. Avoid -use of such things. - -Do not pass values of constants such as F_*, O_*, errno values, etc. across -platforms. - -Please refer compat-errno.h for more details about errno handling inside -glusterfs for cross platform. - -* Specific issues - -- The argp library is available only on Linux through glibc, but for other - platforms glusterfs has already included argp-standalone library which will - statically linked during the glusterfs build. - -- Extended attribute calls (setxattr, listxattr, etc.) have differing prototypes - on different platforms. See compat.h for macro definitions to resolve this, also - read out the specific extended attribute documentation for your platforms. - ------------------------------------------- -Last revised: Thu Feb 28 13:58:07 IST 2008 ------------------------------------------- diff --git a/doc/qa/qa-client.vol b/doc/qa/qa-client.vol deleted file mode 100644 index 176dda5892a..00000000000 --- a/doc/qa/qa-client.vol +++ /dev/null @@ -1,170 +0,0 @@ -# This spec file should be used for testing before any release -# - -# 1st client -volume client1 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport -# option transport.ib-verbs.work-request-send-size 131072 -# option transport.ib-verbs.work-request-send-count 64 -# option transport.ib-verbs.work-request-recv-size 131072 -# option transport.ib-verbs.work-request-recv-count 64 - option remote-host 127.0.0.1 - option remote-subvolume ra1 -end-volume - -# 2nd client -volume client2 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra2 -end-volume - -# 3rd client -volume client3 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra3 -end-volume - -# 4th client -volume client4 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra4 -end-volume - -# 5th client -volume client5 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra5 -end-volume - -# 6th client -volume client6 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra6 -end-volume - -# 7th client -volume client7 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra7 -end-volume - -# 8th client -volume client8 - type protocol/client - option transport-type tcp # for TCP/IP transport -# option transport-type ib-sdp # for Infiniband transport -# option transport-type ib-verbs # for ib-verbs transport - option remote-host 127.0.0.1 - option remote-subvolume ra8 -end-volume - -# 1st Stripe (client1 client2) -volume stripe1 - type cluster/stripe - subvolumes client1 client2 - option block-size 128KB # all striped in 128kB block -end-volume - -# 2st Stripe (client3 client4) -volume stripe2 - type cluster/stripe - subvolumes client3 client4 - option block-size 128KB # all striped in 128kB block -end-volume - -# 3st Stripe (client5 client6) -volume stripe3 - type cluster/stripe - subvolumes client5 client6 - option block-size 128KB # all striped in 128kB block -end-volume - -# 4st Stripe (client7 client8) -volume stripe4 - type cluster/stripe - subvolumes client7 client8 - option block-size 128KB # all striped in 128kB block -end-volume - - -# 1st replicate -volume replicate1 - type cluster/replicate - subvolumes stripe1 stripe2 -end-volume - -# 2nd replicate -volume replicate2 - type cluster/replicate - subvolumes stripe3 stripe4 -end-volume - -volume ns - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option remote-subvolume brick-ns -end-volume - -# Unify -volume unify0 - type cluster/unify - subvolumes replicate1 replicate2 -# subvolumes stripe1 stripe3 - option namespace ns - option scheduler rr # random # alu # nufa - option rr.limits.min-free-disk 1GB -# option alu.order x -# option alu.x.entry-threshold -# option alu.x.exit-threshold -end-volume - - -# ==== Performance Translators ==== -# The default options for performance translators should be the best for 90+% of the cases -volume iot - type performance/io-threads - subvolumes unify0 -end-volume - -volume wb - type performance/write-behind - subvolumes iot -end-volume - -volume ioc - type performance/io-cache - subvolumes wb -end-volume - -volume ra - type performance/read-ahead - subvolumes ioc -end-volume diff --git a/doc/qa/qa-high-avail-client.vol b/doc/qa/qa-high-avail-client.vol deleted file mode 100644 index 69cb8dd30f1..00000000000 --- a/doc/qa/qa-high-avail-client.vol +++ /dev/null @@ -1,17 +0,0 @@ -volume client - type protocol/client - option transport-type tcp - option remote-host localhost - option transport.socket.remote-port 7001 - option remote-subvolume server1-iot -end-volume - -volume ra - type performance/read-ahead - subvolumes client -end-volume - -volume wb - type performance/write-behind - subvolumes ra -end-volume diff --git a/doc/qa/qa-high-avail-server.vol b/doc/qa/qa-high-avail-server.vol deleted file mode 100644 index 3556b9dae99..00000000000 --- a/doc/qa/qa-high-avail-server.vol +++ /dev/null @@ -1,344 +0,0 @@ - -# -- server 1 -- -volume server1-posix1 - type storage/posix - option directory /tmp/ha-export1/ -end-volume - -volume server1-ns1 - type storage/posix - option directory /tmp/ha-export-ns1/ -end-volume - -volume server1-client2 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7002 - option remote-subvolume server2-posix2 -end-volume - -volume server1-ns2 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7002 - option remote-subvolume server2-ns2 -end-volume - -volume server1-client3 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7003 - option remote-subvolume server3-posix3 -end-volume - -volume server1-ns3 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7003 - option remote-subvolume server3-ns3 -end-volume - -volume server1-io1 - type performance/io-threads - option thread-count 8 - subvolumes server1-posix1 -end-volume - - -volume server1-io2 - type performance/io-threads - option thread-count 8 - subvolumes server1-client2 -end-volume - -volume server1-io3 - type performance/io-threads - option thread-count 8 - subvolumes server1-client3 -end-volume - -volume server1-ns-io1 - type performance/io-threads - option thread-count 8 - subvolumes server1-ns1 -end-volume - -volume server1-ns-io2 - type performance/io-threads - option thread-count 8 - subvolumes server1-ns2 -end-volume - -volume server1-ns-io3 - type performance/io-threads - option thread-count 8 - subvolumes server1-ns3 -end-volume - -volume server1-ns-replicate - type cluster/replicate - subvolumes server1-ns-io1 server1-ns-io2 server1-ns-io3 -end-volume - -volume server1-storage-replicate - type cluster/replicate - subvolumes server1-io1 server1-io2 server1-io3 -end-volume - -volume server1-unify - type cluster/unify - #option self-heal off - subvolumes server1-storage-replicate - option namespace server1-ns-replicate - option scheduler rr -end-volume - -volume server1-iot - type performance/io-threads - option thread-count 8 - subvolumes server1-unify -end-volume - -volume server1 - type protocol/server - option transport-type tcp - subvolumes server1-iot - option transport.socket.listen-port 7001 - option auth.addr.server1-posix1.allow * - option auth.addr.server1-ns1.allow * - option auth.addr.server1-iot.allow * -end-volume - - -# == Server2 == -volume server2-client1 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7001 - option remote-subvolume server1-posix1 -end-volume - -volume server2-ns1 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7001 - option remote-subvolume server1-ns1 -end-volume - -volume server2-posix2 - type storage/posix - option directory /tmp/ha-export2/ -end-volume - -volume server2-ns2 - type storage/posix - option directory /tmp/ha-export-ns2/ -end-volume - -volume server2-client3 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7003 - option remote-subvolume server3-posix3 -end-volume - -volume server2-ns3 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7003 - option remote-subvolume server3-ns3 -end-volume - -volume server2-io1 - type performance/io-threads - option thread-count 8 - subvolumes server2-client1 -end-volume - - -volume server2-io2 - type performance/io-threads - option thread-count 8 - subvolumes server2-posix2 -end-volume - -volume server2-io3 - type performance/io-threads - option thread-count 8 - subvolumes server2-client3 -end-volume - -volume server2-ns-io1 - type performance/io-threads - option thread-count 8 - subvolumes server2-ns1 -end-volume - -volume server2-ns-io2 - type performance/io-threads - option thread-count 8 - subvolumes server2-ns2 -end-volume - -volume server2-ns-io3 - type performance/io-threads - option thread-count 8 - subvolumes server2-ns3 -end-volume - -volume server2-ns-replicate - type cluster/replicate - subvolumes server2-ns-io1 server2-ns-io2 server2-ns-io3 -end-volume - -volume server2-storage-replicate - type cluster/replicate - subvolumes server2-io2 server2-io3 server2-io1 -end-volume - -volume server2-unify - type cluster/unify - option self-heal off - subvolumes server2-storage-replicate - option namespace server2-ns-replicate - option scheduler rr -end-volume - -volume server2-iot - type performance/io-threads - option thread-count 8 - subvolumes server2-unify -end-volume - -volume server2 - type protocol/server - option transport-type tcp - subvolumes server2-iot - option transport.socket.listen-port 7002 - option auth.addr.server2-posix2.allow * - option auth.addr.server2-ns2.allow * - option auth.addr.server2-iot.allow * -end-volume - -# == server 3 == -volume server3-client1 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7001 - option remote-subvolume server1-posix1 -end-volume - -volume server3-ns1 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7001 - option remote-subvolume server1-ns1 -end-volume - -volume server3-client2 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7002 - option remote-subvolume server2-posix2 -end-volume - -volume server3-ns2 - type protocol/client - option transport-type tcp - option remote-host 127.0.0.1 - option transport.socket.remote-port 7002 - option remote-subvolume server2-ns2 -end-volume - -volume server3-posix3 - type storage/posix - option directory /tmp/ha-export3/ -end-volume - -volume server3-ns3 - type storage/posix - option directory /tmp/ha-export-ns3/ -end-volume - -volume server3-io1 - type performance/io-threads - option thread-count 8 - subvolumes server3-client1 -end-volume - - -volume server3-io2 - type performance/io-threads - option thread-count 8 - subvolumes server3-client2 -end-volume - -volume server3-io3 - type performance/io-threads - option thread-count 8 - subvolumes server3-posix3 -end-volume - -volume server3-ns-io1 - type performance/io-threads - option thread-count 8 - subvolumes server3-ns1 -end-volume - -volume server3-ns-io2 - type performance/io-threads - option thread-count 8 - subvolumes server3-ns2 -end-volume - -volume server3-ns-io3 - type performance/io-threads - option thread-count 8 - subvolumes server3-ns3 -end-volume - -volume server3-ns-replicate - type cluster/replicate - subvolumes server3-ns-io1 server3-ns-io2 server3-ns-io3 -end-volume - -volume server3-storage-replicate - type cluster/replicate - subvolumes server3-io3 server3-io2 server3-io1 -end-volume - -volume server3-unify - type cluster/unify - option self-heal off - subvolumes server3-storage-replicate - option namespace server3-ns-replicate - option scheduler rr -end-volume - -volume server3-iot - type performance/io-threads - option thread-count 8 - subvolumes server3-unify -end-volume - -volume server3 - type protocol/server - option transport-type tcp - subvolumes server3-iot - option transport.socket.listen-port 7003 - option auth.addr.server3-posix3.allow * - option auth.addr.server3-ns3.allow * - option auth.addr.server3-iot.allow * -end-volume - diff --git a/doc/qa/qa-server.vol b/doc/qa/qa-server.vol deleted file mode 100644 index 1c245c324ad..00000000000 --- a/doc/qa/qa-server.vol +++ /dev/null @@ -1,284 +0,0 @@ -# This spec file should be used for testing before any release -# - -# Namespace posix -volume brick-ns - type storage/posix # POSIX FS translator - option directory /tmp/export-ns # Export this directory -end-volume - -# 1st server - -volume brick1 - type storage/posix # POSIX FS translator - option directory /tmp/export1 # Export this directory -end-volume - -# == Posix-Locks == - volume plocks1 - type features/posix-locks -# option mandatory on - subvolumes brick1 - end-volume - -volume iot1 - type performance/io-threads - subvolumes plocks1 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb1 - type performance/write-behind - subvolumes iot1 -# option <key> <value> -end-volume - -volume ra1 - type performance/read-ahead - subvolumes wb1 -# option <key> <value> -end-volume - -volume brick2 - type storage/posix # POSIX FS translator - option directory /tmp/export2 # Export this directory -end-volume - -# == TrashCan Translator == -# volume trash2 -# type features/trash -# option trash-dir /.trashcan -# subvolumes brick2 -# end-volume - -# == Posix-Locks == -volume plocks2 - type features/posix-locks -# option <something> <something> - subvolumes brick2 -end-volume - -volume iot2 - type performance/io-threads - subvolumes plocks2 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb2 - type performance/write-behind - subvolumes iot2 -# option <key> <value> -end-volume - -volume ra2 - type performance/read-ahead - subvolumes wb2 -# option <key> <value> -end-volume - -volume brick3 - type storage/posix # POSIX FS translator - option directory /tmp/export3 # Export this directory -end-volume - -# == TrashCan Translator == -# volume trash3 -# type features/trash -# option trash-dir /.trashcan -# subvolumes brick3 -# end-volume - -# == Posix-Locks == -volume plocks3 - type features/posix-locks -# option <something> <something> - subvolumes brick3 -end-volume - -volume iot3 - type performance/io-threads - subvolumes plocks3 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb3 - type performance/write-behind - subvolumes iot3 -# option <key> <value> -end-volume - -volume ra3 - type performance/read-ahead - subvolumes wb3 -# option <key> <value> -end-volume - -volume brick4 - type storage/posix # POSIX FS translator - option directory /tmp/export4 # Export this directory -end-volume - -# == Posix-Locks == -volume plocks4 - type features/posix-locks -# option <something> <something> - subvolumes brick4 -end-volume - -volume iot4 - type performance/io-threads - subvolumes plocks4 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb4 - type performance/write-behind - subvolumes iot4 -# option <key> <value> -end-volume - -volume ra4 - type performance/read-ahead - subvolumes wb4 -# option <key> <value> -end-volume - -volume brick5 - type storage/posix # POSIX FS translator - option directory /tmp/export5 # Export this directory -end-volume - - -# == Posix-Locks == -volume plocks5 - type features/posix-locks -# option <something> <something> - subvolumes brick5 -end-volume - -volume iot5 - type performance/io-threads - subvolumes plocks5 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb5 - type performance/write-behind - subvolumes iot5 -# option <key> <value> -end-volume - -volume ra5 - type performance/read-ahead - subvolumes wb5 -# option <key> <value> -end-volume - -volume brick6 - type storage/posix # POSIX FS translator - option directory /tmp/export6 # Export this directory -end-volume - -# == Posix-Locks == -volume plocks6 - type features/posix-locks -# option <something> <something> - subvolumes brick6 -end-volume - -volume iot6 - type performance/io-threads - subvolumes plocks6 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb6 - type performance/write-behind - subvolumes iot6 -# option <key> <value> -end-volume - -volume ra6 - type performance/read-ahead - subvolumes wb6 -# option <key> <value> -end-volume - -volume brick7 - type storage/posix # POSIX FS translator - option directory /tmp/export7 # Export this directory -end-volume - -# == Posix-Locks == -volume plocks7 - type features/posix-locks -# option <something> <something> - subvolumes brick7 -end-volume - -volume iot7 - type performance/io-threads - subvolumes plocks7 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb7 - type performance/write-behind - subvolumes iot7 -# option <key> <value> -end-volume - -volume ra7 - type performance/read-ahead - subvolumes wb7 -# option <key> <value> -end-volume - -volume brick8 - type storage/posix # POSIX FS translator - option directory /tmp/export8 # Export this directory -end-volume - -# == Posix-Locks == -volume plocks8 - type features/posix-locks -# option <something> <something> - subvolumes brick8 -end-volume - -volume iot8 - type performance/io-threads - subvolumes plocks8 # change properly if above commented volumes needs to be included -# option <key> <value> -end-volume - -volume wb8 - type performance/write-behind - subvolumes iot8 -# option <key> <value> -end-volume - -volume ra8 - type performance/read-ahead - subvolumes wb8 -# option <key> <value> -end-volume - -volume server8 - type protocol/server - subvolumes ra8 ra1 ra2 ra3 ra4 ra5 ra6 ra7 brick-ns - option transport-type tcp # For TCP/IP transport -# option transport-type ib-sdp # For Infiniband transport -# option transport-type ib-verbs # For ib-verbs transport - option client-volume-filename /examples/qa-client.vol - option auth.addr.ra1.allow * # Allow access to "stat8" volume - option auth.addr.ra2.allow * # Allow access to "stat8" volume - option auth.addr.ra3.allow * # Allow access to "stat8" volume - option auth.addr.ra4.allow * # Allow access to "stat8" volume - option auth.addr.ra5.allow * # Allow access to "stat8" volume - option auth.addr.ra6.allow * # Allow access to "stat8" volume - option auth.addr.ra7.allow * # Allow access to "stat8" volume - option auth.addr.ra8.allow * # Allow access to "stat8" volume - option auth.addr.brick-ns.allow * # Allow access to "stat8" volume -end-volume - diff --git a/doc/replicate.lyx b/doc/replicate.lyx deleted file mode 100644 index d11a92beedd..00000000000 --- a/doc/replicate.lyx +++ /dev/null @@ -1,797 +0,0 @@ -#LyX 1.4.2 created this file. For more info see http://www.lyx.org/ -\lyxformat 245 -\begin_document -\begin_header -\textclass article -\language english -\inputencoding auto -\fontscheme default -\graphics default -\paperfontsize default -\spacing single -\papersize default -\use_geometry false -\use_amsmath 1 -\cite_engine basic -\use_bibtopic false -\paperorientation portrait -\secnumdepth 3 -\tocdepth 3 -\paragraph_separation skip -\defskip medskip -\quotes_language english -\papercolumns 1 -\papersides 1 -\paperpagestyle default -\tracking_changes false -\output_changes false -\end_header - -\begin_body - -\begin_layout Title - -\size larger -Automatic File Replication (replicate) in GlusterFS -\end_layout - -\begin_layout Author -Vikas Gorur -\family typewriter -\size larger -<vikas@gluster.com> -\end_layout - -\begin_layout Standard -\begin_inset ERT -status open - -\begin_layout Standard - - -\backslash -hrule -\end_layout - -\end_inset - - -\end_layout - -\begin_layout Section* -Overview -\end_layout - -\begin_layout Standard -This document describes the design and usage of the replicate translator in GlusterFS. - This document is valid for the 1.4.x releases, and not earlier ones. -\end_layout - -\begin_layout Standard -The replicate translator of GlusterFS aims to keep identical copies of a file - on all its subvolumes, as far as possible. - It tries to do this by performing all filesystem mutation operations (writing - data, creating files, changing ownership, etc.) on all its subvolumes in - such a way that if an operation succeeds on atleast one subvolume, all - other subvolumes can later be brought up to date. -\end_layout - -\begin_layout Standard -In the rest of the document the terms -\begin_inset Quotes eld -\end_inset - -subvolume -\begin_inset Quotes erd -\end_inset - - and -\begin_inset Quotes eld -\end_inset - -server -\begin_inset Quotes erd -\end_inset - - are used interchangeably, trusting that it will cause no confusion to the - reader. -\end_layout - -\begin_layout Section* -Usage -\end_layout - -\begin_layout Standard -A sample volume declaration for replicate looks like this: -\end_layout - -\begin_layout Standard -\begin_inset ERT -status open - -\begin_layout Standard - - -\backslash -begin{verbatim} -\end_layout - -\begin_layout Standard - -volume replicate -\end_layout - -\begin_layout Standard - - type cluster/replicate -\end_layout - -\begin_layout Standard - - # options, see below for description -\end_layout - -\begin_layout Standard - - subvolumes brick1 brick2 -\end_layout - -\begin_layout Standard - -end-volume -\end_layout - -\begin_layout Standard - - -\backslash -end{verbatim} -\end_layout - -\begin_layout Standard - -\end_layout - -\begin_layout Standard - -\end_layout - -\begin_layout Standard - -\end_layout - -\end_inset - - -\end_layout - -\begin_layout Standard -This defines an replicate volume with two subvolumes, brick1, and brick2. - For replicate to work properly, it is essential that its subvolumes support -\series bold -extended attributes -\series default -. - This means that you should choose a backend filesystem that supports extended - attributes, like XFS, ReiserFS, or Ext3. -\end_layout - -\begin_layout Standard -The storage volumes used as backend for replicate -\emph on -must -\emph default - have a posix-locks volume loaded above them. -\end_layout - -\begin_layout Standard -\begin_inset ERT -status open - -\begin_layout Standard - - -\backslash -begin{verbatim} -\end_layout - -\begin_layout Standard - -volume brick1 -\end_layout - -\begin_layout Standard - - type features/posix-locks -\end_layout - -\begin_layout Standard - - subvolumes brick1-ds -\end_layout - -\begin_layout Standard - -end-volume -\end_layout - -\begin_layout Standard - - -\backslash -end{verbatim} -\end_layout - -\end_inset - - -\end_layout - -\begin_layout Section* -Design -\end_layout - -\begin_layout Subsection* -Read algorithm -\end_layout - -\begin_layout Standard -All operations that do not modify the file or directory are sent to all - the subvolumes and the first successful reply is returned to the application. -\end_layout - -\begin_layout Standard -The read() system call (reading data from a file) is an exception. - For read() calls, replicate tries to do load balancing by sending all reads from - a particular file to a particular server. -\end_layout - -\begin_layout Standard -The read algorithm is also affected by the option read-subvolume; see below - for details. -\end_layout - -\begin_layout Subsection* -Classes of file operations -\end_layout - -\begin_layout Standard -replicate divides all filesystem write operations into three classes: -\end_layout - -\begin_layout Itemize - -\series bold -data: -\series default -Operations that modify the contents of a file (write, truncate). -\end_layout - -\begin_layout Itemize - -\series bold -metadata: -\series default -Operations that modify attributes of a file or directory (permissions, ownership -, etc.). -\end_layout - -\begin_layout Itemize - -\series bold -entry: -\series default -Operations that create or delete directory entries (mkdir, create, rename, - rmdir, unlink, etc.). -\end_layout - -\begin_layout Subsection* -Locking and Change Log -\end_layout - -\begin_layout Standard -To ensure consistency across subvolumes, replicate holds a lock whenever a modificatio -n is being made to a file or directory. - By default, replicate considers the first subvolume as the sole lock server. - However, the number of lock servers can be increased upto the total number - of subvolumes. -\end_layout - -\begin_layout Standard -The change log is a set of extended attributes associated with files and - directories that replicate maintains. - The change log keeps track of the changes made to files and directories - (data, metadata, entry) so that the self-heal algorithm knows which copy - of a file or directory is the most recent one. -\end_layout - -\begin_layout Subsection* -Write algorithm -\end_layout - -\begin_layout Standard -The algorithm for all write operations (data, metadata, entry) is: -\end_layout - -\begin_layout Enumerate -Lock the file (or directory) on all of the lock servers (see options below). -\end_layout - -\begin_layout Enumerate -Write change log entries on all servers. -\end_layout - -\begin_layout Enumerate -Perform the operation. -\end_layout - -\begin_layout Enumerate -Erase change log entries. -\end_layout - -\begin_layout Enumerate -Unlock the file (or directory) on all of the lock servers. -\end_layout - -\begin_layout Standard -The above algorithm is a simplified version intended for general users. - Please refer to the source code for the full details. -\end_layout - -\begin_layout Subsection* -Self-Heal -\end_layout - -\begin_layout Standard -replicate automatically tries to fix any inconsistencies it detects among different - copies of a file. - It uses information in the change log to determine which copy is the -\begin_inset Quotes eld -\end_inset - -correct -\begin_inset Quotes erd -\end_inset - - version. -\end_layout - -\begin_layout Standard -Self-heal is triggered when a file or directory is first -\begin_inset Quotes eld -\end_inset - -accessed -\begin_inset Quotes erd -\end_inset - -, that is, the first time any operation is attempted on it. - The self-heal algorithm does the following things: -\end_layout - -\begin_layout Standard -If the entry being accessed is a directory: -\end_layout - -\begin_layout Itemize -The contents of the -\begin_inset Quotes eld -\end_inset - -correct -\begin_inset Quotes erd -\end_inset - - version is replicated on all subvolumes, by deleting entries and creating - entries as necessary. -\end_layout - -\begin_layout Standard -If the entry being accessed is a file: -\end_layout - -\begin_layout Itemize -If the file does not exist on some subvolumes, it is created. -\end_layout - -\begin_layout Itemize -If there is a mismatch in the size of the file, or ownership, or permission, - it is fixed. -\end_layout - -\begin_layout Itemize -If the change log indicates that some copies need updating, they are updated. -\end_layout - -\begin_layout Subsection* -Split-brain -\end_layout - -\begin_layout Standard -It may happen that one replicate client can access only some of the servers in - a cluster and another replicate client can access the remaining servers. - Or it may happen that in a cluster of two servers, one server goes down - and comes back up, but the other goes down immediately. - Both these scenarios result in a -\begin_inset Quotes eld -\end_inset - -split-brain -\begin_inset Quotes erd -\end_inset - -. -\end_layout - -\begin_layout Standard -In a split-brain situation, there will be two or more copies of a file, - all of which are -\begin_inset Quotes eld -\end_inset - -correct -\begin_inset Quotes erd -\end_inset - - in some sense. - replicate without manual intervention has no way of knowing what to do, since - it cannot consider any single copy as definitive, nor does it know of any - meaningful way to merge the copies. -\end_layout - -\begin_layout Standard -If replicate detects that a split-brain has happened on a file, it disallows opening - of that file. - You will have to manually resolve the conflict by deleting all but one - copy of the file. - Alternatively you can set an automatic split-brain resolution policy by - using the `favorite-child' option (see below). -\end_layout - -\begin_layout Section* -Translator Options -\end_layout - -\begin_layout Standard -replicate accepts the following options: -\end_layout - -\begin_layout Subsection* -read-subvolume (default: none) -\end_layout - -\begin_layout Standard -The value of this option must be the name of a subvolume. - If given, all read operations are sent to only the specified subvolume, - instead of being balanced across all subvolumes. -\end_layout - -\begin_layout Subsection* -favorite-child (default: none) -\end_layout - -\begin_layout Standard -The value of this option must be the name of a subvolume. - If given, the specified subvolume will be preferentially used in resolving - conflicts ( -\begin_inset Quotes eld -\end_inset - -split-brain -\begin_inset Quotes erd -\end_inset - -). - This means if a discrepancy is noticed in the attributes or content of - a file, the copy on the `favorite-child' will be considered the definitive - version and its contents will -\emph on -overwrite -\emph default -the contents of all other copies. - Use this option with caution! It is possible to -\emph on -lose data -\emph default - with this option. - If you are in doubt, do not specify this option. -\end_layout - -\begin_layout Subsection* -Self-heal options -\end_layout - -\begin_layout Standard -Setting any of these options to -\begin_inset Quotes eld -\end_inset - -off -\begin_inset Quotes erd -\end_inset - - prevents that kind of self-heal from being done on a file or directory. - For example, if metadata self-heal is turned off, permissions and ownership - are no longer fixed automatically. -\end_layout - -\begin_layout Subsubsection* -data-self-heal (default: on) -\end_layout - -\begin_layout Standard -Enable/disable self-healing of file contents. -\end_layout - -\begin_layout Subsubsection* -metadata-self-heal (default: off) -\end_layout - -\begin_layout Standard -Enable/disable self-healing of metadata (permissions, ownership, modification - times). -\end_layout - -\begin_layout Subsubsection* -entry-self-heal (default: on) -\end_layout - -\begin_layout Standard -Enable/disable self-healing of directory entries. -\end_layout - -\begin_layout Subsection* -Change Log options -\end_layout - -\begin_layout Standard -If any of these options is turned off, it disables writing of change log - entries for that class of file operations. - That is, steps 2 and 4 of the write algorithm (see above) are not done. - Note that if the change log is not written, the self-heal algorithm cannot - determine the -\begin_inset Quotes eld -\end_inset - -correct -\begin_inset Quotes erd -\end_inset - - version of a file and hence self-heal will only be able to fix -\begin_inset Quotes eld -\end_inset - -obviously -\begin_inset Quotes erd -\end_inset - - wrong things (such as a file existing on only one node). -\end_layout - -\begin_layout Subsubsection* -data-change-log (default: on) -\end_layout - -\begin_layout Standard -Enable/disable writing of change log for data operations. -\end_layout - -\begin_layout Subsubsection* -metadata-change-log (default: on) -\end_layout - -\begin_layout Standard -Enable/disable writing of change log for metadata operations. -\end_layout - -\begin_layout Subsubsection* -entry-change-log (default: on) -\end_layout - -\begin_layout Standard -Enable/disable writing of change log for entry operations. -\end_layout - -\begin_layout Subsection* -Locking options -\end_layout - -\begin_layout Standard -These options let you specify the number of lock servers to use for each - class of file operations. - The default values are satisfactory in most cases. - If you are extra paranoid, you may want to increase the values. - However, be very cautious if you set the data- or entry- lock server counts - to zero, since this can result in -\emph on -lost data. - -\emph default - For example, if you set the data-lock-server-count to zero, and two application -s write to the same region of a file, there is a possibility that none of - your servers will have all the data. - In other words, the copies will be -\emph on -inconsistent -\emph default -, and -\emph on -incomplete -\emph default -. - Do not set data- and entry- lock server counts to zero unless you absolutely - know what you are doing and agree to not hold GlusterFS responsible for - any lost data. -\end_layout - -\begin_layout Subsubsection* -data-lock-server-count (default: 1) -\end_layout - -\begin_layout Standard -Number of lock servers to use for data operations. -\end_layout - -\begin_layout Subsubsection* -metadata-lock-server-count (default: 0) -\end_layout - -\begin_layout Standard -Number of lock servers to use for metadata operations. -\end_layout - -\begin_layout Subsubsection* -entry-lock-server-count (default: 1) -\end_layout - -\begin_layout Standard -Number of lock servers to use for entry operations. -\end_layout - -\begin_layout Section* -Known Issues -\end_layout - -\begin_layout Subsection* -Self-heal of file with more than one link (hard links): -\end_layout - -\begin_layout Standard -Consider two servers, A and B. - Assume A is down, and the user creates a file `new' as a hard link to a - file `old'. - When A comes back up, replicate will see that the file `new' does not exist on - A, and self-heal will create the file and copy the contents from B. - However, now on server A the file `new' is not a link to the file `old' - but an entirely different file. -\end_layout - -\begin_layout Standard -We know of no easy way to fix this problem, but we will try to fix it in - forthcoming releases. -\end_layout - -\begin_layout Subsection* -File re-opening after a server comes back up: -\end_layout - -\begin_layout Standard -If a server A goes down and comes back up, any files which were opened while - A was down and are still open will not have their writes replicated on - A. - In other words, data replication only happens on those servers which were - alive when the file was opened. -\end_layout - -\begin_layout Standard -This is a rather tricky issue but we hope to fix it very soon. -\end_layout - -\begin_layout Section* -Frequently Asked Questions -\end_layout - -\begin_layout Subsection* -1. - How can I force self-heal to happen? -\end_layout - -\begin_layout Standard -You can force self-heal to happen on your cluster by running a script or - a command that accesses every file. - A simple way to do it would be: -\end_layout - -\begin_layout Standard -\begin_inset ERT -status open - -\begin_layout Standard - -\end_layout - -\begin_layout Standard - - -\backslash -begin{verbatim} -\end_layout - -\begin_layout Standard - -$ ls -lR -\end_layout - -\begin_layout Standard - - -\backslash -end{verbatim} -\end_layout - -\begin_layout Standard - -\end_layout - -\end_inset - - -\end_layout - -\begin_layout Standard -Run the command in all directories which you want to forcibly self-heal. -\end_layout - -\begin_layout Subsection* -2. - Which backend filesystem should I use for replicate? -\end_layout - -\begin_layout Standard -You can use any backend filesystem that supports extended attributes. - We know of users successfully using XFR, ReiserFS, and Ext3. -\end_layout - -\begin_layout Subsection* -3. - What can I do to improve replicate performance? -\end_layout - -\begin_layout Standard -Try loading performance translators such as io-threads, write-behind, io-cache, - and read-ahead depending on your workload. - If you are willing to sacrifice correctness in corner cases, you can experiment - with the lock-server-count and the change-log options (see above). - As warned earlier, be very careful! -\end_layout - -\begin_layout Subsection* -4. - How can I selectively replicate files? -\end_layout - -\begin_layout Standard -There is no support for selective replication in replicate itself. - You can achieve selective replication by loading the unify translator over - replicate, and using the switch scheduler. - Configure unify with two subvolumes, one of them being replicate. - Using the switch scheduler, schedule all files for which you need replication - to the replicate subvolume. - Consult unify and switch documentation for more details. -\end_layout - -\begin_layout Section* -Contact -\end_layout - -\begin_layout Standard -If you need more assistance on replicate, contact us on the mailing list <gluster-user -s@gluster.org> (visit gluster.org for details on how to subscribe). -\end_layout - -\begin_layout Standard -Send you comments and suggestions about this document to <vikas@gluster.com>. -\end_layout - -\end_body -\end_document diff --git a/doc/replicate.pdf b/doc/replicate.pdf Binary files differdeleted file mode 100644 index b7212af2b4e..00000000000 --- a/doc/replicate.pdf +++ /dev/null diff --git a/doc/solaris-related-xattrs.txt b/doc/solaris-related-xattrs.txt deleted file mode 100644 index e26efa5d189..00000000000 --- a/doc/solaris-related-xattrs.txt +++ /dev/null @@ -1,44 +0,0 @@ - Solaris Extended Attributes - -In solaris extended attributes are logically supported as files -within the filesystem. The file system is therefore augmented -with an orthogonal namespace of file attributes. Attribute values -are accessed by file descriptors obtained through a special attribute -interface. This type of logical view of "attributes as files" allows -the leveraging of existing file system interface functionality to -support the construction, deletion and manipulation of attributes. - -But as we have tested through this functionality provided by Solaris -we have come accross two major issues as written below. - -1. Symlink XATTR_NOFOLLOW not present for creating extended attributes - directly on the symlinks like other platforms Linux,MAC-OSX,BSD etc. - An implementation is present for O_NOFOLLOW for "openat()" call sets - up errno ELOOP whenever encountered with a symlink and also another - implementation AT_SYMLINK_NOFOLLOW which is not present for calls like - "attropen(), openat()" - - a snippet of test code which helped us understand this behaviour - -------------------------------------- - attrfd = attropen (path, key, - flags|AT_SYMLINK_NOFOLLOW|O_CREAT|O_WRONLY|O_NOFOLLOW, 0777); - if (attrfd >= 0) { - ftruncate (attrfd, 0); - ret = write (attrfd, value, size); - close (attrfd); - } else { - fprintf (stderr, "Couldn't set extended attribute for %s (%d)\n", - path, errno); - } - -------------------------------------- - -2. Extended attribute support for special files like device files, fifo files - is not supported under solaris. - -Apart from these glitches almost everything regarding porting functionality -for extended attribute calls has been properly implemented in compat.c -with writing wrapper around functions over -"attropen()", "openat()", "unlinkat()" - - - diff --git a/doc/stat-prefetch-design.txt b/doc/stat-prefetch-design.txt deleted file mode 100644 index 06d0ad37e7d..00000000000 --- a/doc/stat-prefetch-design.txt +++ /dev/null @@ -1,154 +0,0 @@ -what is stat-prefetch? -====================== -It is a translator which caches the dentries read in readdir. This dentry -list is stored in the context of fd. Later when lookup happens on -[parent-inode, basename (path)] combination, this list is searched for the -basename. The dentry thus searched is used to fill up the stat corresponding -to path being looked upon, thereby short-cutting lookup calls. This cache is -preserved till closedir is called on the fd. The purpose of this translator -is to optimize operations like 'ls -l', where a readdir is followed by -lookup (stat) calls on each directory entry. - -1. stat-prefetch harnesses the efficiency of short lookup calls - (saves network roundtrip time for lookup calls from being accounted to - the stat call). -2. To maintain the correctness, it does lookup-behind - lookup is winded to - underlying translators after it is unwound to upper translators. - lookup-behind is necessary as inode gets populated in server inode table - only in lookup-cbk and also because various translators store their - contexts in inode contexts during lookup calls. - -fops to be implemented: -======================= -* lookup - 1. check the dentry cache stored in context of fds opened by the same process - on parent inode for basename. If found unwind with cached stat, else wind - the lookup call to underlying translators. - 2. stat is stored in the context of inode if the path being looked upon - happens to be directory. This stat will be used to fill postparent stat - when lookup happens on any of the directory contents. - -* readdir - 1. cache the direntries returned in readdir_cbk in the context of fd. - 2. if the readdir is happening on non-expected offsets (means a seekdir/rewinddir - has happened), cache has to be flushed. - 3. delete the entry corresponding to basename of path on which fd is opened - from cache stored in parent. - -* chmod/fchmod - delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode, since these calls change st_mode and st_ctime of - stat. - -* chown/fchown - delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode, since these calls change st_uid/st_gid and - st_ctime of stat. - -* truncate/ftruncate - delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode, since these calls change st_size/st_mtime of stat. - -* utimens - delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode, since this call changes st_atime/st_mtime of stat. - -* readlink - delete the entry corresponding to basename from cache stored in context of fds - opened on parent inode, since this call changes st_atime of stat. - -* unlink - 1. delete the entry corresponding to basename from cache stored in context of - fds, opened on parent directory containing the file being unlinked. - 2. delete the entry corresponding to basename of parent directory from cache - of grand-parent. - -* rmdir - 1. delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode. - 2. remove the entire cache from all fds opened on inode corresponding to - directory being removed. - 3. delete the entry correspondig to basename of parent from cache stored in - grand-parent. - -* readv - delete the entry corresponding to basename from cache stored in context of fds - opened on parent inode, since readv changes st_atime of file. - -* writev - delete the entry corresponding to basename from cache stored in context of fds - opened on parent inode, since writev can possibly change st_size and definitely - changes st_mtime of file. - -* fsync - there is a confusion here as to whether fsync updates mtime/ctimes. Disk based - filesystems (atleast ext2) just writes the times stored in inode to disk - during fsync and not the time at which fsync is being done. But in glusterfs, - a translator like write-behind actually sends writes during fsync which will - change mtime/ctime. Hence stat-prefetch implements fsync to delete the entry - corresponding to basename from cache stored in context of fds opened on parent - inode. - -* rename - 1. remove entry corresponding to oldname from cache stored in fd contexts of - oldparent. - 2. remove entry corresponding to newname from cache stored in fd contexts of - newparent. - 3. remove entry corresponding to oldparent from cache stored in - old-grand-parent, since removing oldname changes st_mtime and st_ctime - of oldparent stat. - 4. remove entry corresponding to newparent from cache stored in - new-grand-parent, since adding newname changes st_mtime and st_ctime - of newparent stat. - 5. if oldname happens to be a directory, remove entire cache from all fds - opened on it. - -* create/mknod/mkdir/symlink/link - delete entry corresponding to basename of parent directory in which these - operations are happening, from cache stored in context of fds opened on - grand-parent, since adding a new entry to a directory changes st_mtime - and st_ctime of parent directory. - -* setxattr/removexattr - delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode, since setxattr changes st_ctime of file. - -* setdents - 1. remove entry corresponding to basename of path on which fd is opened from - cache stored in context of fds opened on parent. - 2. for each of the entry in the direntry list, delete from cache stored in - context of fd, the entry corresponding to basename of path being passed. - -* getdents - 1. remove entry corresponding to basename of path on which fd is opened from - cache stored in parent, since getdents changes st_atime. - 2. remove entries corresponding to symbolic links from cache, since readlink - would've changed st_atime. - -* checksum - delete the entry corresponding to basename from cache stored in context of - fds opened on parent inode, since st_atime is changed during this call. - -* xattrop/fxattrop - delete the entry corresponding to basename from cache stored in context of fds - opened on parent inode, since these calls modify st_ctime of file. - -callbacks to be implemented: -============================ -* releasedir - free the context stored in fd. - -* forget - dree the stat if the inode corresponds to a directory. - -limitations: -============ -* since a readdir does not return extended attributes of file, if need_xattr is - set, short-cutting of lookup does not happen and lookup is passed to - underlying translators. - -* posix_readdir does not check whether the dentries are spanning across multiple - mount points. Hence it is not transforming inode numbers in stat buffers if - posix is configured to allow export directory spanning on multiple mountpoints. - This is a bug which needs to be fixed. posix_readdir should treat dentries the - same way as if lookup is happening on dentries. diff --git a/doc/translator-options.txt b/doc/translator-options.txt deleted file mode 100644 index 278ef5b0083..00000000000 --- a/doc/translator-options.txt +++ /dev/null @@ -1,224 +0,0 @@ -mount/fuse: - * direct-io-mode GF_OPTION_TYPE_BOOL on|off|yes|no - * mount-point (mountpoint) GF_OPTION_TYPE_PATH <any-posix-valid-path> - * attribute-timeout GF_OPTION_TYPE_DOUBLE 0.0 - * entry-timeout GF_OPTION_TYPE_DOUBLE 0.0 - -protocol/server: - * transport-type GF_OPTION_TYPE_STR tcp|socket|ib-verbs|unix|ib-sdp| - tcp/client|ib-verbs/client - * volume-filename.* GF_OPTION_TYPE_PATH - * inode-lru-limit GF_OPTION_TYPE_INT 0-(1 * GF_UNIT_MB) - * client-volume-filename GF_OPTION_TYPE_PATH - -protocol/client: - * username GF_OPTION_TYPE_ANY - * password GF_OPTION_TYPE_ANY - * transport-type GF_OPTION_TYPE_STR tcp|socket|ib-verbs|unix|ib-sdp| - tcp/client|ib-verbs/client - * remote-host GF_OPTION_TYPE_ANY - * remote-subvolume GF_OPTION_TYPE_ANY - * transport-timeout GF_OPTION_TYPE_TIME 5-1013 - -cluster/replicate: - * read-subvolume GF_OPTION_TYPE_XLATOR - * favorite-child GF_OPTION_TYPE_XLATOR - * data-self-heal GF_OPTION_TYPE_BOOL - * metadata-self-heal GF_OPTION_TYPE_BOOL - * entry-self-heal GF_OPTION_TYPE_BOOL - * data-change-log GF_OPTION_TYPE_BOOL - * metadata-change-log GF_OPTION_TYPE_BOOL - * entry-change-log GF_OPTION_TYPE_BOOL - * data-lock-server-count GF_OPTION_TYPE_INT 0 - * metadata-lock-server-count GF_OPTION_TYPE_INT 0 - * entry-lock-server-count GF_OPTION_TYPE_INT 0 - -cluster/distribute: - * lookup-unhashed GF_OPTION_TYPE_BOOL - -cluster/unify: - * namespace GF_OPTION_TYPE_XLATOR - * scheduler GF_OPTION_TYPE_STR alu|rr|random|nufa|switch - * self-heal GF_OPTION_TYPE_STR foreground|background|off - * optimist GF_OPTION_TYPE_BOOL - -cluster/nufa: - local-volume-name GF_OPTION_TYPE_XLATOR - -cluster/stripe: - * block-size GF_OPTION_TYPE_ANY - * use-xattr GF_OPTION_TYPE_BOOL - -debug/trace: - * include-ops (include) GF_OPTION_TYPE_STR - * exclude-ops (exclude) GF_OPTION_TYPE_STR - -encryption/rot-13: - * encrypt-write GF_OPTION_TYPE_BOOL - * decrypt-read GF_OPTION_TYPE_BOOL - -features/path-convertor: - * start-offset GF_OPTION_TYPE_INT 0-4095 - * end-offset GF_OPTION_TYPE_INT 1-4096 - * replace-with GF_OPTION_TYPE_ANY - -features/trash: - * trash-dir GF_OPTION_TYPE_PATH - -features/locks: - * mandatory-locks (mandatory) GF_OPTION_TYPE_BOOL - -features/filter: - * root-squashing GF_OPTION_TYPE_BOOL - * read-only GF_OPTION_TYPE_BOOL - * fixed-uid GF_OPTION_TYPE_INT - * fixed-gid GF_OPTION_TYPE_INT - * translate-uid GF_OPTION_TYPE_ANY - * translate-gid GF_OPTION_TYPE_ANY - * filter-uid GF_OPTION_TYPE_ANY - * filter-gid GF_OPTION_TYPE_ANY - -features/quota: - * min-free-disk-limit GF_OPTION_TYPE_PERCENT - * refresh-interval GF_OPTION_TYPE_TIME - * disk-usage-limit GF_OPTION_TYPE_SIZET - -storage/posix: - * o-direct GF_OPTION_TYPE_BOOL - * directory GF_OPTION_TYPE_PATH - * export-statfs-size GF_OPTION_TYPE_BOOL - * mandate-attribute GF_OPTION_TYPE_BOOL - -storage/bdb: - * directory GF_OPTION_TYPE_PATH - * logdir GF_OPTION_TYPE_PATH - * errfile GF_OPTION_TYPE_PATH - * dir-mode GF_OPTION_TYPE_ANY - * file-mode GF_OPTION_TYPE_ANY - * page-size GF_OPTION_TYPE_SIZET - * lru-limit GF_OPTION_TYPE_INT - * lock-timeout GF_OPTION_TYPE_TIME - * checkpoint-timeout GF_OPTION_TYPE_TIME - * transaction-timeout GF_OPTION_TYPE_TIME - * mode GF_OPTION_TYPE_BOOL - * access-mode GF_OPTION_TYPE_STR - -performance/read-ahead: - * force-atime-update GF_OPTION_TYPE_BOOL - * page-size GF_OPTION_TYPE_SIZET (64 * GF_UNIT_KB)-(2 * GF_UNIT_MB) - * page-count GF_OPTION_TYPE_INT 1-16 - -performance/write-behind: - * flush-behind GF_OPTION_TYPE_BOOL - * aggregate-size GF_OPTION_TYPE_SIZET (128 * GF_UNIT_KB)-(4 * GF_UNIT_MB) - * window-size GF_OPTION_TYPE_SIZET (512 * GF_UNIT_KB)-(1 * GF_UNIT_GB) - * enable-O_SYNC GF_OPTION_TYPE_BOOL - * disable-for-first-nbytes GF_OPTION_TYPE_SIZET 1 - (1 * GF_UNIT_MB) - -performance/symlink-cache: - -performance/io-threads: - * thread-count GF_OPTION_TYPE_INT 1-32 - -performance/io-cache: - * priority GF_OPTION_TYPE_ANY - * cache-timeout (force-revalidate-timeout) GF_OPTION_TYPE_INT 0-60 - * page-size GF_OPTION_TYPE_SIZET (16 * GF_UNIT_KB)-(4 * GF_UNIT_MB) - * cache-size GF_OPTION_TYPE_SIZET (4 * GF_UNIT_MB)-(6 * GF_UNIT_GB) - -performance/quick-read: - * cache-timeout GF_OPTION_TYPE_INT 1-60 - * max-file-size GF_OPTION_TYPE_SIZET 0-(1000 * GF_UNIT_KB) - -auth: -- addr: - * auth.addr.*.allow GF_OPTION_TYPE_ANY - * auth.addr.*.reject GF_OPTION_TYPE_ANY - -- login: - * auth.login.*.allow GF_OPTION_TYPE_ANY - * auth.login.*.password GF_OPTION_TYPE_ANY - -scheduler/alu: - * scheduler.alu.order (alu.order) - GF_OPTION_TYPE_ANY - * scheduler.alu.disk-usage.entry-threshold (alu.disk-usage.entry-threshold) - GF_OPTION_TYPE_SIZET - * scheduler.alu.disk-usage.exit-threshold (alu.disk-usage.exit-threshold) - GF_OPTION_TYPE_SIZET - * scheduler.alu.write-usage.entry-threshold (alu.write-usage.entry-threshold) - GF_OPTION_TYPE_SIZET - * scheduler.alu.write-usage.exit-threshold (alu.write-usage.exit-threshold) - GF_OPTION_TYPE_SIZET - * scheduler.alu.read-usage.entry-threshold (alu.read-usage.entry-threshold) - GF_OPTION_TYPE_SIZET - * scheduler.alu.read-usage.exit-threshold (alu.read-usage.exit-threshold) - GF_OPTION_TYPE_SIZET - * scheduler.alu.open-files-usage.entry-threshold (alu.open-files-usage.entry-threshold) - GF_OPTION_TYPE_INT - * scheduler.alu.open-files-usage.exit-threshold (alu.open-files-usage.exit-threshold) - GF_OPTION_TYPE_INT - * scheduler.read-only-subvolumes (alu.read-only-subvolumes) - GF_OPTION_TYPE_ANY - * scheduler.refresh-interval (alu.refresh-interval) - GF_OPTION_TYPE_TIME - * scheduler.limits.min-free-disk (alu.limits.min-free-disk) - GF_OPTION_TYPE_PERCENT - * scheduler.alu.stat-refresh.num-file-create (alu.stat-refresh.num-file-create) - GF_OPTION_TYPE_INT - -scheduler/nufa: - * scheduler.refresh-interval (nufa.refresh-interval) - GF_OPTION_TYPE_TIME - * scheduler.limits.min-free-disk (nufa.limits.min-free-disk) - GF_OPTION_TYPE_PERCENT - * scheduler.local-volume-name (nufa.local-volume-name) - GF_OPTION_TYPE_XLATOR - -scheduler/random: - * scheduler.refresh-interval (random.refresh-interval) GF_OPTION_TYPE_TIME - * scheduler.limits.min-free-disk (random.limits.min-free-disk) GF_OPTION_TYPE_PERCENT - -scheduler/rr: - * scheduler.refresh-interval (rr.refresh-interval) GF_OPTION_TYPE_TIME - * scheduler.limits.min-free-disk (rr.limits.min-free-disk) GF_OPTION_TYPE_PERCENT - * scheduler.read-only-subvolumes (rr.read-only-subvolumes) GF_OPTION_TYPE_ANY - -scheduler/switch: - * scheduler.read-only-subvolumes (switch.read-only-subvolumes) GF_OPTION_TYPE_ANY - * scheduler.local-volume-name (switch.nufa.local-volume-name) GF_OPTION_TYPE_XLATOR - * scheduler.switch.case (switch.case) GF_OPTION_TYPE_ANY - -transport/ib-verbs: - * transport.ib-verbs.port (ib-verbs-port) GF_OPTION_TYPE_INT 1-4 - check the option by 'ibv_devinfo' - * transport.ib-verbs.mtu (ib-verbs-mtu) GF_OPTION_TYPE_INT - * transport.ib-verbs.device-name (ib-verbs-device-name) GF_OPTION_TYPE_ANY, - check by 'ibv_devinfo' - * transport.ib-verbs.work-request-send-size (ib-verbs-work-request-send-size) - GF_OPTION_TYPE_INT, - * transport.ib-verbs.work-request-recv-size (ib-verbs-work-request-recv-size) - GF_OPTION_TYPE_INT - * transport.ib-verbs.work-request-send-count (ib-verbs-work-request-send-count) - GF_OPTION_TYPE_INT - * transport.ib-verbs.work-request-recv-count (ib-verbs-work-request-recv-count) - GF_OPTION_TYPE_INT - * remote-port (transport.remote-port,transport.ib-verbs.remote-port) - GF_OPTION_TYPE_INT - * transport.ib-verbs.listen-port GF_OPTION_TYPE_INT - * transport.ib-verbs.connect-path (connect-path) GF_OPTION_TYPE_ANY - * transport.ib-verbs.bind-path (bind-path) GF_OPTION_TYPE_ANY - * transport.ib-verbs.listen-path (listen-path) GF_OPTION_TYPE_ANY - * transport.address-family (address-family) GF_OPTION_TYPE_STR inet|inet6|inet/inet6| - inet6/inet|unix|inet-sdp - -transport/socket: - * transport.remote-port (remote-port,transport.socket.remote-port) GF_OPTION_TYPE_INT - * transport.socket.listen-port (listen-port) GF_OPTION_TYPE_INT - * transport.socket.bind-address (bind-address) GF_OPTION_TYPE_ANY - * transport.socket.connect-path (connect-path) GF_OPTION_TYPE_ANY - * transport.socket.bind-path (bind-path) GF_OPTION_TYPE_ANY - * transport.socket.listen-path (listen-path) GF_OPTION_TYPE_ANY - * transport.address-family (address-family) GF_OPTION_TYPE_STR inet|inet6| - inet/inet6|inet6/inet| - unix|inet-sdp diff --git a/doc/user-guide/Makefile.am b/doc/user-guide/Makefile.am deleted file mode 100644 index 800e7321d79..00000000000 --- a/doc/user-guide/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -info_TEXINFOS = user-guide.texi -CLEANFILES = *~ -DISTCLEANFILES = .deps/*.P *.info *vti diff --git a/doc/user-guide/advanced-stripe.odg b/doc/user-guide/advanced-stripe.odg Binary files differdeleted file mode 100644 index 7686d7091b2..00000000000 --- a/doc/user-guide/advanced-stripe.odg +++ /dev/null diff --git a/doc/user-guide/advanced-stripe.pdf b/doc/user-guide/advanced-stripe.pdf Binary files differdeleted file mode 100644 index ec8b03dcfbb..00000000000 --- a/doc/user-guide/advanced-stripe.pdf +++ /dev/null diff --git a/doc/user-guide/colonO-icon.jpg b/doc/user-guide/colonO-icon.jpg Binary files differdeleted file mode 100644 index 3e66f7a2775..00000000000 --- a/doc/user-guide/colonO-icon.jpg +++ /dev/null diff --git a/doc/user-guide/fdl.texi b/doc/user-guide/fdl.texi deleted file mode 100644 index 92cfa81a79f..00000000000 --- a/doc/user-guide/fdl.texi +++ /dev/null @@ -1,454 +0,0 @@ - -@c @node GNU Free Documentation License -@c @appendixsec GNU Free Documentation License - -@cindex FDL, GNU Free Documentation License -@center Version 1.2, November 2002 - -@display -Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307, USA - -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. -@end display - -@enumerate 0 -@item -PREAMBLE - -The purpose of this License is to make a manual, textbook, or other -functional and useful document @dfn{free} in the sense of freedom: to -assure everyone the effective freedom to copy and redistribute it, -with or without modifying it, either commercially or noncommercially. -Secondarily, this License preserves for the author and publisher a way -to get credit for their work, while not being considered responsible -for modifications made by others. - -This License is a kind of ``copyleft'', which means that derivative -works of the document must themselves be free in the same sense. It -complements the GNU Affero General Public License, which is a copyleft -license designed for free software. - -We have designed this License in order to use it for manuals for free -software, because free software needs free documentation: a free -program should come with manuals providing the same freedoms that the -software does. But this License is not limited to software manuals; -it can be used for any textual work, regardless of subject matter or -whether it is published as a printed book. We recommend this License -principally for works whose purpose is instruction or reference. - -@item -APPLICABILITY AND DEFINITIONS - -This License applies to any manual or other work, in any medium, that -contains a notice placed by the copyright holder saying it can be -distributed under the terms of this License. Such a notice grants a -world-wide, royalty-free license, unlimited in duration, to use that -work under the conditions stated herein. The ``Document'', below, -refers to any such manual or work. Any member of the public is a -licensee, and is addressed as ``you''. You accept the license if you -copy, modify or distribute the work in a way requiring permission -under copyright law. - -A ``Modified Version'' of the Document means any work containing the -Document or a portion of it, either copied verbatim, or with -modifications and/or translated into another language. - -A ``Secondary Section'' is a named appendix or a front-matter section -of the Document that deals exclusively with the relationship of the -publishers or authors of the Document to the Document's overall -subject (or to related matters) and contains nothing that could fall -directly within that overall subject. (Thus, if the Document is in -part a textbook of mathematics, a Secondary Section may not explain -any mathematics.) The relationship could be a matter of historical -connection with the subject or with related matters, or of legal, -commercial, philosophical, ethical or political position regarding -them. - -The ``Invariant Sections'' are certain Secondary Sections whose titles -are designated, as being those of Invariant Sections, in the notice -that says that the Document is released under this License. If a -section does not fit the above definition of Secondary then it is not -allowed to be designated as Invariant. The Document may contain zero -Invariant Sections. If the Document does not identify any Invariant -Sections then there are none. - -The ``Cover Texts'' are certain short passages of text that are listed, -as Front-Cover Texts or Back-Cover Texts, in the notice that says that -the Document is released under this License. A Front-Cover Text may -be at most 5 words, and a Back-Cover Text may be at most 25 words. - -A ``Transparent'' copy of the Document means a machine-readable copy, -represented in a format whose specification is available to the -general public, that is suitable for revising the document -straightforwardly with generic text editors or (for images composed of -pixels) generic paint programs or (for drawings) some widely available -drawing editor, and that is suitable for input to text formatters or -for automatic translation to a variety of formats suitable for input -to text formatters. A copy made in an otherwise Transparent file -format whose markup, or absence of markup, has been arranged to thwart -or discourage subsequent modification by readers is not Transparent. -An image format is not Transparent if used for any substantial amount -of text. A copy that is not ``Transparent'' is called ``Opaque''. - -Examples of suitable formats for Transparent copies include plain -@sc{ascii} without markup, Texinfo input format, La@TeX{} input -format, @acronym{SGML} or @acronym{XML} using a publicly available -@acronym{DTD}, and standard-conforming simple @acronym{HTML}, -PostScript or @acronym{PDF} designed for human modification. Examples -of transparent image formats include @acronym{PNG}, @acronym{XCF} and -@acronym{JPG}. Opaque formats include proprietary formats that can be -read and edited only by proprietary word processors, @acronym{SGML} or -@acronym{XML} for which the @acronym{DTD} and/or processing tools are -not generally available, and the machine-generated @acronym{HTML}, -PostScript or @acronym{PDF} produced by some word processors for -output purposes only. - -The ``Title Page'' means, for a printed book, the title page itself, -plus such following pages as are needed to hold, legibly, the material -this License requires to appear in the title page. For works in -formats which do not have any title page as such, ``Title Page'' means -the text near the most prominent appearance of the work's title, -preceding the beginning of the body of the text. - -A section ``Entitled XYZ'' means a named subunit of the Document whose -title either is precisely XYZ or contains XYZ in parentheses following -text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as ``Acknowledgements'', -``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' -of such a section when you modify the Document means that it remains a -section ``Entitled XYZ'' according to this definition. - -The Document may include Warranty Disclaimers next to the notice which -states that this License applies to the Document. These Warranty -Disclaimers are considered to be included by reference in this -License, but only as regards disclaiming warranties: any other -implication that these Warranty Disclaimers may have is void and has -no effect on the meaning of this License. - -@item -VERBATIM COPYING - -You may copy and distribute the Document in any medium, either -commercially or noncommercially, provided that this License, the -copyright notices, and the license notice saying this License applies -to the Document are reproduced in all copies, and that you add no other -conditions whatsoever to those of this License. You may not use -technical measures to obstruct or control the reading or further -copying of the copies you make or distribute. However, you may accept -compensation in exchange for copies. If you distribute a large enough -number of copies you must also follow the conditions in section 3. - -You may also lend copies, under the same conditions stated above, and -you may publicly display copies. - -@item -COPYING IN QUANTITY - -If you publish printed copies (or copies in media that commonly have -printed covers) of the Document, numbering more than 100, and the -Document's license notice requires Cover Texts, you must enclose the -copies in covers that carry, clearly and legibly, all these Cover -Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on -the back cover. Both covers must also clearly and legibly identify -you as the publisher of these copies. The front cover must present -the full title with all words of the title equally prominent and -visible. You may add other material on the covers in addition. -Copying with changes limited to the covers, as long as they preserve -the title of the Document and satisfy these conditions, can be treated -as verbatim copying in other respects. - -If the required texts for either cover are too voluminous to fit -legibly, you should put the first ones listed (as many as fit -reasonably) on the actual cover, and continue the rest onto adjacent -pages. - -If you publish or distribute Opaque copies of the Document numbering -more than 100, you must either include a machine-readable Transparent -copy along with each Opaque copy, or state in or with each Opaque copy -a computer-network location from which the general network-using -public has access to download using public-standard network protocols -a complete Transparent copy of the Document, free of added material. -If you use the latter option, you must take reasonably prudent steps, -when you begin distribution of Opaque copies in quantity, to ensure -that this Transparent copy will remain thus accessible at the stated -location until at least one year after the last time you distribute an -Opaque copy (directly or through your agents or retailers) of that -edition to the public. - -It is requested, but not required, that you contact the authors of the -Document well before redistributing any large number of copies, to give -them a chance to provide you with an updated version of the Document. - -@item -MODIFICATIONS - -You may copy and distribute a Modified Version of the Document under -the conditions of sections 2 and 3 above, provided that you release -the Modified Version under precisely this License, with the Modified -Version filling the role of the Document, thus licensing distribution -and modification of the Modified Version to whoever possesses a copy -of it. In addition, you must do these things in the Modified Version: - -@enumerate A -@item -Use in the Title Page (and on the covers, if any) a title distinct -from that of the Document, and from those of previous versions -(which should, if there were any, be listed in the History section -of the Document). You may use the same title as a previous version -if the original publisher of that version gives permission. - -@item -List on the Title Page, as authors, one or more persons or entities -responsible for authorship of the modifications in the Modified -Version, together with at least five of the principal authors of the -Document (all of its principal authors, if it has fewer than five), -unless they release you from this requirement. - -@item -State on the Title page the name of the publisher of the -Modified Version, as the publisher. - -@item -Preserve all the copyright notices of the Document. - -@item -Add an appropriate copyright notice for your modifications -adjacent to the other copyright notices. - -@item -Include, immediately after the copyright notices, a license notice -giving the public permission to use the Modified Version under the -terms of this License, in the form shown in the Addendum below. - -@item -Preserve in that license notice the full lists of Invariant Sections -and required Cover Texts given in the Document's license notice. - -@item -Include an unaltered copy of this License. - -@item -Preserve the section Entitled ``History'', Preserve its Title, and add -to it an item stating at least the title, year, new authors, and -publisher of the Modified Version as given on the Title Page. If -there is no section Entitled ``History'' in the Document, create one -stating the title, year, authors, and publisher of the Document as -given on its Title Page, then add an item describing the Modified -Version as stated in the previous sentence. - -@item -Preserve the network location, if any, given in the Document for -public access to a Transparent copy of the Document, and likewise -the network locations given in the Document for previous versions -it was based on. These may be placed in the ``History'' section. -You may omit a network location for a work that was published at -least four years before the Document itself, or if the original -publisher of the version it refers to gives permission. - -@item -For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve -the Title of the section, and preserve in the section all the -substance and tone of each of the contributor acknowledgements and/or -dedications given therein. - -@item -Preserve all the Invariant Sections of the Document, -unaltered in their text and in their titles. Section numbers -or the equivalent are not considered part of the section titles. - -@item -Delete any section Entitled ``Endorsements''. Such a section -may not be included in the Modified Version. - -@item -Do not retitle any existing section to be Entitled ``Endorsements'' or -to conflict in title with any Invariant Section. - -@item -Preserve any Warranty Disclaimers. -@end enumerate - -If the Modified Version includes new front-matter sections or -appendices that qualify as Secondary Sections and contain no material -copied from the Document, you may at your option designate some or all -of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. -These titles must be distinct from any other section titles. - -You may add a section Entitled ``Endorsements'', provided it contains -nothing but endorsements of your Modified Version by various -parties---for example, statements of peer review or that the text has -been approved by an organization as the authoritative definition of a -standard. - -You may add a passage of up to five words as a Front-Cover Text, and a -passage of up to 25 words as a Back-Cover Text, to the end of the list -of Cover Texts in the Modified Version. Only one passage of -Front-Cover Text and one of Back-Cover Text may be added by (or -through arrangements made by) any one entity. If the Document already -includes a cover text for the same cover, previously added by you or -by arrangement made by the same entity you are acting on behalf of, -you may not add another; but you may replace the old one, on explicit -permission from the previous publisher that added the old one. - -The author(s) and publisher(s) of the Document do not by this License -give permission to use their names for publicity for or to assert or -imply endorsement of any Modified Version. - -@item -COMBINING DOCUMENTS - -You may combine the Document with other documents released under this -License, under the terms defined in section 4 above for modified -versions, provided that you include in the combination all of the -Invariant Sections of all of the original documents, unmodified, and -list them all as Invariant Sections of your combined work in its -license notice, and that you preserve all their Warranty Disclaimers. - -The combined work need only contain one copy of this License, and -multiple identical Invariant Sections may be replaced with a single -copy. If there are multiple Invariant Sections with the same name but -different contents, make the title of each such section unique by -adding at the end of it, in parentheses, the name of the original -author or publisher of that section if known, or else a unique number. -Make the same adjustment to the section titles in the list of -Invariant Sections in the license notice of the combined work. - -In the combination, you must combine any sections Entitled ``History'' -in the various original documents, forming one section Entitled -``History''; likewise combine any sections Entitled ``Acknowledgements'', -and any sections Entitled ``Dedications''. You must delete all -sections Entitled ``Endorsements.'' - -@item -COLLECTIONS OF DOCUMENTS - -You may make a collection consisting of the Document and other documents -released under this License, and replace the individual copies of this -License in the various documents with a single copy that is included in -the collection, provided that you follow the rules of this License for -verbatim copying of each of the documents in all other respects. - -You may extract a single document from such a collection, and distribute -it individually under this License, provided you insert a copy of this -License into the extracted document, and follow this License in all -other respects regarding verbatim copying of that document. - -@item -AGGREGATION WITH INDEPENDENT WORKS - -A compilation of the Document or its derivatives with other separate -and independent documents or works, in or on a volume of a storage or -distribution medium, is called an ``aggregate'' if the copyright -resulting from the compilation is not used to limit the legal rights -of the compilation's users beyond what the individual works permit. -When the Document is included in an aggregate, this License does not -apply to the other works in the aggregate which are not themselves -derivative works of the Document. - -If the Cover Text requirement of section 3 is applicable to these -copies of the Document, then if the Document is less than one half of -the entire aggregate, the Document's Cover Texts may be placed on -covers that bracket the Document within the aggregate, or the -electronic equivalent of covers if the Document is in electronic form. -Otherwise they must appear on printed covers that bracket the whole -aggregate. - -@item -TRANSLATION - -Translation is considered a kind of modification, so you may -distribute translations of the Document under the terms of section 4. -Replacing Invariant Sections with translations requires special -permission from their copyright holders, but you may include -translations of some or all Invariant Sections in addition to the -original versions of these Invariant Sections. You may include a -translation of this License, and all the license notices in the -Document, and any Warranty Disclaimers, provided that you also include -the original English version of this License and the original versions -of those notices and disclaimers. In case of a disagreement between -the translation and the original version of this License or a notice -or disclaimer, the original version will prevail. - -If a section in the Document is Entitled ``Acknowledgements'', -``Dedications'', or ``History'', the requirement (section 4) to Preserve -its Title (section 1) will typically require changing the actual -title. - -@item -TERMINATION - -You may not copy, modify, sublicense, or distribute the Document except -as expressly provided for under this License. Any other attempt to -copy, modify, sublicense or distribute the Document is void, and will -automatically terminate your rights under this License. However, -parties who have received copies, or rights, from you under this -License will not have their licenses terminated so long as such -parties remain in full compliance. - -@item -FUTURE REVISIONS OF THIS LICENSE - -The Free Software Foundation may publish new, revised versions -of the GNU Free Documentation License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. See -@uref{http://www.gnu.org/copyleft/}. - -Each version of the License is given a distinguishing version number. -If the Document specifies that a particular numbered version of this -License ``or any later version'' applies to it, you have the option of -following the terms and conditions either of that specified version or -of any later version that has been published (not as a draft) by the -Free Software Foundation. If the Document does not specify a version -number of this License, you may choose any version ever published (not -as a draft) by the Free Software Foundation. -@end enumerate - -@page -@c @appendixsubsec ADDENDUM: How to use this License for your -@c documents -@subsection ADDENDUM: How to use this License for your documents - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and -license notices just after the title page: - -@smallexample -@group - Copyright (C) @var{year} @var{your name}. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.2 - or any later version published by the Free Software Foundation; - with no Invariant Sections, no Front-Cover Texts, and no Back-Cover - Texts. A copy of the license is included in the section entitled ``GNU - Free Documentation License''. -@end group -@end smallexample - -If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, -replace the ``with...Texts.'' line with this: - -@smallexample -@group - with the Invariant Sections being @var{list their titles}, with - the Front-Cover Texts being @var{list}, and with the Back-Cover Texts - being @var{list}. -@end group -@end smallexample - -If you have Invariant Sections without Cover Texts, or some other -combination of the three, merge those two alternatives to suit the -situation. - -If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of -free software license, such as the GNU Affero General Public License, -to permit their use in free software. - -@c Local Variables: -@c ispell-local-pdict: "ispell-dict" -@c End: - diff --git a/doc/user-guide/fuse.odg b/doc/user-guide/fuse.odg Binary files differdeleted file mode 100644 index 61bd103c78b..00000000000 --- a/doc/user-guide/fuse.odg +++ /dev/null diff --git a/doc/user-guide/fuse.pdf b/doc/user-guide/fuse.pdf Binary files differdeleted file mode 100644 index a7d13faff56..00000000000 --- a/doc/user-guide/fuse.pdf +++ /dev/null diff --git a/doc/user-guide/ha.odg b/doc/user-guide/ha.odg Binary files differdeleted file mode 100644 index e4b8b72d08b..00000000000 --- a/doc/user-guide/ha.odg +++ /dev/null diff --git a/doc/user-guide/ha.pdf b/doc/user-guide/ha.pdf Binary files differdeleted file mode 100644 index e372c0ab03e..00000000000 --- a/doc/user-guide/ha.pdf +++ /dev/null diff --git a/doc/user-guide/stripe.odg b/doc/user-guide/stripe.odg Binary files differdeleted file mode 100644 index 79441bf1452..00000000000 --- a/doc/user-guide/stripe.odg +++ /dev/null diff --git a/doc/user-guide/stripe.pdf b/doc/user-guide/stripe.pdf Binary files differdeleted file mode 100644 index b94446feb56..00000000000 --- a/doc/user-guide/stripe.pdf +++ /dev/null diff --git a/doc/user-guide/unify.odg b/doc/user-guide/unify.odg Binary files differdeleted file mode 100644 index ccaa9bf16f9..00000000000 --- a/doc/user-guide/unify.odg +++ /dev/null diff --git a/doc/user-guide/unify.pdf b/doc/user-guide/unify.pdf Binary files differdeleted file mode 100644 index c22027f66e7..00000000000 --- a/doc/user-guide/unify.pdf +++ /dev/null diff --git a/doc/user-guide/user-guide.info b/doc/user-guide/user-guide.info deleted file mode 100644 index 494c0e94ee4..00000000000 --- a/doc/user-guide/user-guide.info +++ /dev/null @@ -1,2697 +0,0 @@ -This is ../../../doc/user-guide/user-guide.info, produced by makeinfo version 4.13 from ../../../doc/user-guide/user-guide.texi. - -START-INFO-DIR-ENTRY -* GlusterFS: (user-guide). GlusterFS distributed filesystem user guide -END-INFO-DIR-ENTRY - - This is the user manual for GlusterFS 2.0. - - Copyright (C) 2007-2010 Gluster, Inc. Permission is granted to -copy, distribute and/or modify this document under the terms of the GNU -Free Documentation License, Version 1.2 or any later version published -by the Free Software Foundation; with no Invariant Sections, no -Front-Cover Texts, and no Back-Cover Texts. A copy of the license is -included in the chapter entitled "GNU Free Documentation License". - - -File: user-guide.info, Node: Top, Next: Acknowledgements, Up: (dir) - -GlusterFS 2.0 User Guide -************************ - -This is the user manual for GlusterFS 2.0. - - Copyright (C) 2007-2010 Gluster, Inc. Permission is granted to -copy, distribute and/or modify this document under the terms of the GNU -Free Documentation License, Version 1.2 or any later version published -by the Free Software Foundation; with no Invariant Sections, no -Front-Cover Texts, and no Back-Cover Texts. A copy of the license is -included in the chapter entitled "GNU Free Documentation License". - -* Menu: - -* Acknowledgements:: -* Introduction:: -* Installation and Invocation:: -* Concepts:: -* Translators:: -* Usage Scenarios:: -* Troubleshooting:: -* GNU Free Documentation Licence:: -* Index:: - - --- The Detailed Node Listing --- - -Installation and Invocation - -* Pre requisites:: -* Getting GlusterFS:: -* Building:: -* Running GlusterFS:: -* A Tutorial Introduction:: - -Running GlusterFS - -* Server:: -* Client:: - -Concepts - -* Filesystems in Userspace:: -* Translator:: -* Volume specification file:: - -Translators - -* Storage Translators:: -* Client and Server Translators:: -* Clustering Translators:: -* Performance Translators:: -* Features Translators:: - -Storage Translators - -* POSIX:: - -Client and Server Translators - -* Transport modules:: -* Client protocol:: -* Server protocol:: - -Clustering Translators - -* Unify:: -* Replicate:: -* Stripe:: - -Performance Translators - -* Read Ahead:: -* Write Behind:: -* IO Threads:: -* IO Cache:: - -Features Translators - -* POSIX Locks:: -* Fixed ID:: - -Miscellaneous Translators - -* ROT-13:: -* Trace:: - - -File: user-guide.info, Node: Acknowledgements, Next: Introduction, Prev: Top, Up: Top - -Acknowledgements -**************** - -GlusterFS continues to be a wonderful and enriching experience for all -of us involved. - - GlusterFS development would not have been possible at this pace if -not for our enthusiastic users. People from around the world have -helped us with bug reports, performance numbers, and feature -suggestions. A huge thanks to them all. - - Matthew Paine - for RPMs & general enthu - - Leonardo Rodrigues de Mello - for DEBs - - Julian Perez & Adam D'Auria - for multi-server tutorial - - Paul England - for HA spec - - Brent Nelson - for many bug reports - - Jacques Mattheij - for Europe mirror. - - Patrick Negri - for TCP non-blocking connect. - http://gluster.org/core-team.php (<list-hacking@gluster.com>) - Gluster - - -File: user-guide.info, Node: Introduction, Next: Installation and Invocation, Prev: Acknowledgements, Up: Top - -1 Introduction -************** - -GlusterFS is a distributed filesystem. It works at the file level, not -block level. - - A network filesystem is one which allows us to access remote files. A -distributed filesystem is one that stores data on multiple machines and -makes them all appear to be a part of the same filesystem. - - Need for distributed filesystems - - * Scalability: A distributed filesystem allows us to store more data - than what can be stored on a single machine. - - * Redundancy: We might want to replicate crucial data on to several - machines. - - * Uniform access: One can mount a remote volume (for example your - home directory) from any machine and access the same data. - -1.1 Contacting us -================= - -You can reach us through the mailing list *gluster-devel* -(<gluster-devel@nongnu.org>). - - You can also find many of the developers on IRC, on the `#gluster' -channel on Freenode (<irc.freenode.net>). - - The GlusterFS documentation wiki is also useful: -<http://gluster.org/docs/index.php/GlusterFS> - - For commercial support, you can contact Gluster at: - - 3194 Winding Vista Common - Fremont, CA 94539 - USA. - - Phone: +1 (510) 354 6801 - Toll free: +1 (888) 813 6309 - Fax: +1 (510) 372 0604 - - You can also email us at <support@gluster.com>. - - -File: user-guide.info, Node: Installation and Invocation, Next: Concepts, Prev: Introduction, Up: Top - -2 Installation and Invocation -***************************** - -* Menu: - -* Pre requisites:: -* Getting GlusterFS:: -* Building:: -* Running GlusterFS:: -* A Tutorial Introduction:: - - -File: user-guide.info, Node: Pre requisites, Next: Getting GlusterFS, Up: Installation and Invocation - -2.1 Pre requisites -================== - -Before installing GlusterFS make sure you have the following components -installed. - -2.1.1 FUSE ----------- - -You'll need FUSE version 2.6.0 or higher to use GlusterFS. You can omit -installing FUSE if you want to build _only_ the server. Note that you -won't be able to mount a GlusterFS filesystem on a machine that does -not have FUSE installed. - - FUSE can be downloaded from: <http://fuse.sourceforge.net/> - - To get the best performance from GlusterFS, however, it is -recommended that you use our patched version of FUSE. See Patched FUSE -for details. - -2.1.2 Patched FUSE ------------------- - -The GlusterFS project maintains a patched version of FUSE meant to be -used with GlusterFS. The patches increase GlusterFS performance. It is -recommended that all users use the patched FUSE. - - The patched FUSE tarball can be downloaded from: - - <ftp://ftp.gluster.com/pub/gluster/glusterfs/fuse/> - - The specific changes made to FUSE are: - - * The communication channel size between FUSE kernel module and - GlusterFS has been increased to 1MB, permitting large reads and - writes to be sent in bigger chunks. - - * The kernel's read-ahead boundry has been extended upto 1MB. - - * Block size returned in the `stat()'/`fstat()' calls tuned to 1MB, - to make cp and similar commands perform I/O using that block size. - - * `flock()' locking support has been added (although some rework in - GlusterFS is needed for perfect compliance). - -2.1.3 libibverbs (optional) ---------------------------- - -This is only needed if you want GlusterFS to use InfiniBand as the -interconnect mechanism between server and client. You can get it from: - - <http://www.openfabrics.org/downloads.htm>. - -2.1.4 Bison and Flex --------------------- - -These should be already installed on most Linux systems. If not, use -your distribution's normal software installation procedures to install -them. Make sure you install the relevant developer packages also. - - -File: user-guide.info, Node: Getting GlusterFS, Next: Building, Prev: Pre requisites, Up: Installation and Invocation - -2.2 Getting GlusterFS -===================== - -There are many ways to get hold of GlusterFS. For a production -deployment, the recommended method is to download the latest release -tarball. Release tarballs are available at: -<http://gluster.org/download.php>. - - If you want the bleeding edge development source, you can get them -from the GNU Arch(1) repository. First you must install GNU Arch -itself. Then register the GlusterFS archive by doing: - - $ tla register-archive http://arch.sv.gnu.org/archives/gluster - - Now you can check out the source itself: - - $ tla get -A gluster@sv.gnu.org glusterfs--mainline--3.0 - - ---------- Footnotes ---------- - - (1) <http://www.gnu.org/software/gnu-arch/> - - -File: user-guide.info, Node: Building, Next: Running GlusterFS, Prev: Getting GlusterFS, Up: Installation and Invocation - -2.3 Building -============ - -You can skip this section if you're installing from RPMs or DEBs. - - GlusterFS uses the Autotools mechanism to build. As such, the -procedure is straight-forward. First, change into the GlusterFS source -directory. - - $ cd glusterfs-<version> - - If you checked out the source from the Arch repository, you'll need -to run `./autogen.sh' first. Note that you'll need to have Autoconf and -Automake installed for this. - - Run `configure'. - - $ ./configure - - The configure script accepts the following options: - -`--disable-ibverbs' - Disable the InfiniBand transport mechanism. - -`--disable-fuse-client' - Disable the FUSE client. - -`--disable-server' - Disable building of the GlusterFS server. - -`--disable-bdb' - Disable building of Berkeley DB based storage translator. - -`--disable-mod_glusterfs' - Disable building of Apache/lighttpd glusterfs plugins. - -`--disable-epoll' - Use poll instead of epoll. - -`--disable-libglusterfsclient' - Disable building of libglusterfsclient - - - Build and install GlusterFS. - - # make install - - The binaries (`glusterfsd' and `glusterfs') will be by default -installed in `/usr/local/sbin/'. Translator, scheduler, and transport -shared libraries will be installed in -`/usr/local/lib/glusterfs/<version>/'. Sample volume specification -files will be in `/usr/local/etc/glusterfs/'. This document itself can -be found in `/usr/local/share/doc/glusterfs/'. If you passed the -`--prefix' argument to the configure script, then replace `/usr/local' -in the preceding paths with the prefix. - - -File: user-guide.info, Node: Running GlusterFS, Next: A Tutorial Introduction, Prev: Building, Up: Installation and Invocation - -2.4 Running GlusterFS -===================== - -* Menu: - -* Server:: -* Client:: - - -File: user-guide.info, Node: Server, Next: Client, Up: Running GlusterFS - -2.4.1 Server ------------- - -The GlusterFS server is necessary to export storage volumes to remote -clients (See *note Server protocol:: for more info). This section -documents the invocation of the GlusterFS server program and all the -command-line options accepted by it. - - Basic Options - -`-f, --volfile=<path>' - Use the volume file as the volume specification. - -`-s, --volfile-server=<hostname>' - Server to get volume file from. This option overrides -volfile - option. - -`-l, --log-file=<path>' - Specify the path for the log file. - -`-L, --log-level=<level>' - Set the log level for the server. Log level should be one of DEBUG, - WARNING, ERROR, CRITICAL, or NONE. - - Advanced Options - -`--debug' - Run in debug mode. This option sets -no-daemon, -log-level to - DEBUG and -log-file to console. - -`-N, --no-daemon' - Run glusterfsd as a foreground process. - -`-p, --pid-file=<path>' - Path for the PID file. - -`--volfile-id=<key>' - 'key' of the volfile to be fetched from server. - -`--volfile-server-port=<port-number>' - Listening port number of volfile server. - -`--volfile-server-transport=[socket|ib-verbs]' - Transport type to get volfile from server. [default: `socket'] - -`--xlator-options=<volume-name.option=value>' - Add/override a translator option for a volume with specified value. - - Miscellaneous Options - -`-?, --help' - Show this help text. - -`--usage' - Display a short usage message. - -`-V, --version' - Show version information. - - -File: user-guide.info, Node: Client, Prev: Server, Up: Running GlusterFS - -2.4.2 Client ------------- - -The GlusterFS client process is necessary to access remote storage -volumes and mount them locally using FUSE. This section documents the -invocation of the client process and all its command-line arguments. - - # glusterfs [options] <mountpoint> - - The `mountpoint' is the directory where you want the GlusterFS -filesystem to appear. Example: - - # glusterfs -f /usr/local/etc/glusterfs-client.vol /mnt - - The command-line options are detailed below. - - Basic Options - -`-f, --volfile=<path>' - Use the volume file as the volume specification. - -`-s, --volfile-server=<hostname>' - Server to get volume file from. This option overrides -volfile - option. - -`-l, --log-file=<path>' - Specify the path for the log file. - -`-L, --log-level=<level>' - Set the log level for the server. Log level should be one of DEBUG, - WARNING, ERROR, CRITICAL, or NONE. - - Advanced Options - -`--debug' - Run in debug mode. This option sets -no-daemon, -log-level to - DEBUG and -log-file to console. - -`-N, --no-daemon' - Run `glusterfs' as a foreground process. - -`-p, --pid-file=<path>' - Path for the PID file. - -`--volfile-id=<key>' - 'key' of the volfile to be fetched from server. - -`--volfile-server-port=<port-number>' - Listening port number of volfile server. - -`--volfile-server-transport=[socket|ib-verbs]' - Transport type to get volfile from server. [default: `socket'] - -`--xlator-options=<volume-name.option=value>' - Add/override a translator option for a volume with specified value. - -`--volume-name=<volume name>' - Volume name in client spec to use. Defaults to the root volume. - - FUSE Options - -`--attribute-timeout=<n>' - Attribute timeout for inodes in the kernel, in seconds. Defaults - to 1 second. - -`--disable-direct-io-mode' - Disable direct I/O mode in FUSE kernel module. - -`-e, --entry-timeout=<n>' - Entry timeout for directory entries in the kernel, in seconds. - Defaults to 1 second. - - Missellaneous Options - -`-?, --help' - Show this help information. - -`-V, --version' - Show version information. - - -File: user-guide.info, Node: A Tutorial Introduction, Prev: Running GlusterFS, Up: Installation and Invocation - -2.5 A Tutorial Introduction -=========================== - -This section will show you how to quickly get GlusterFS up and running. -We'll configure GlusterFS as a simple network filesystem, with one -server and one client. In this mode of usage, GlusterFS can serve as a -replacement for NFS. - - We'll make use of two machines; call them _server_ and _client_ (If -you don't want to setup two machines, just run everything that follows -on the same machine). In the examples that follow, the shell prompts -will use these names to clarify the machine on which the command is -being run. For example, a command that should be run on the server will -be shown with the prompt: - - [root@server]# - - Our goal is to make a directory on the _server_ (say, `/export') -accessible to the _client_. - - First of all, get GlusterFS installed on both the machines, as -described in the previous sections. Make sure you have the FUSE kernel -module loaded. You can ensure this by running: - - [root@server]# modprobe fuse - - Before we can run the GlusterFS client or server programs, we need -to write two files called _volume specifications_ (equivalently refered -to as _volfiles_). The volfile describes the _translator tree_ on a -node. The next chapter will explain the concepts of `translator' and -`volume specification' in detail. For now, just assume that the volfile -is like an NFS `/etc/export' file. - - On the server, create a text file somewhere (we'll assume the path -`/tmp/glusterfsd.vol') with the following contents. - - volume colon-o - type storage/posix - option directory /export - end-volume - - volume server - type protocol/server - subvolumes colon-o - option transport-type tcp - option auth.addr.colon-o.allow * - end-volume - - A brief explanation of the file's contents. The first section -defines a storage volume, named "colon-o" (the volume names are -arbitrary), which exports the `/export' directory. The second section -defines options for the translator which will make the storage volume -accessible remotely. It specifies `colon-o' as a subvolume. This -defines the _translator tree_, about which more will be said in the -next chapter. The two options specify that the TCP protocol is to be -used (as opposed to InfiniBand, for example), and that access to the -storage volume is to be provided to clients with any IP address at all. -If you wanted to restrict access to this server to only your subnet for -example, you'd specify something like `192.168.1.*' in the second -option line. - - On the client machine, create the following text file (again, we'll -assume the path to be `/tmp/glusterfs-client.vol'). Replace -_server-ip-address_ with the IP address of your server machine. If you -are doing all this on a single machine, use `127.0.0.1'. - - volume client - type protocol/client - option transport-type tcp - option remote-host _server-ip-address_ - option remote-subvolume colon-o - end-volume - - Now we need to start both the server and client programs. To start -the server: - - [root@server]# glusterfsd -f /tmp/glusterfs-server.vol - - To start the client: - - [root@client]# glusterfs -f /tmp/glusterfs-client.vol /mnt/glusterfs - - You should now be able to see the files under the server's `/export' -directory in the `/mnt/glusterfs' directory on the client. That's it; -GlusterFS is now working as a network file system. - - -File: user-guide.info, Node: Concepts, Next: Translators, Prev: Installation and Invocation, Up: Top - -3 Concepts -********** - -* Menu: - -* Filesystems in Userspace:: -* Translator:: -* Volume specification file:: - - -File: user-guide.info, Node: Filesystems in Userspace, Next: Translator, Up: Concepts - -3.1 Filesystems in Userspace -============================ - -A filesystem is usually implemented in kernel space. Kernel space -development is much harder than userspace development. FUSE is a kernel -module/library that allows us to write a filesystem completely in -userspace. - - FUSE consists of a kernel module which interacts with the userspace -implementation using a device file `/dev/fuse'. When a process makes a -syscall on a FUSE filesystem, VFS hands the request to the FUSE module, -which writes the request to `/dev/fuse'. The userspace implementation -polls `/dev/fuse', and when a request arrives, processes it and writes -the result back to `/dev/fuse'. The kernel then reads from the device -file and returns the result to the user process. - - In case of GlusterFS, the userspace program is the GlusterFS client. -The control flow is shown in the diagram below. The GlusterFS client -services the request by sending it to the server, which in turn hands -it to the local POSIX filesystem. - - - Fig 1. Control flow in GlusterFS - - -File: user-guide.info, Node: Translator, Next: Volume specification file, Prev: Filesystems in Userspace, Up: Concepts - -3.2 Translator -============== - -The _translator_ is the most important concept in GlusterFS. In fact, -GlusterFS is nothing but a collection of translators working together, -forming a translator _tree_. - - The idea of a translator is perhaps best understood using an -analogy. Consider the VFS in the Linux kernel. The VFS abstracts the -various filesystem implementations (such as EXT3, ReiserFS, XFS, etc.) -supported by the kernel. When an application calls the kernel to -perform an operation on a file, the kernel passes the request on to the -appropriate filesystem implementation. - - For example, let's say there are two partitions on a Linux machine: -`/', which is an EXT3 partition, and `/usr', which is a ReiserFS -partition. Now if an application wants to open a file called, say, -`/etc/fstab', then the kernel will internally pass the request to the -EXT3 implementation. If on the other hand, an application wants to -read a file called `/usr/src/linux/CREDITS', then the kernel will call -upon the ReiserFS implementation to do the job. - - The "filesystem implementation" objects are analogous to GlusterFS -translators. A GlusterFS translator implements all the filesystem -operations. Whereas in VFS there is a two-level tree (with the kernel -at the root and all the filesystem implementation as its children), in -GlusterFS there exists a more elaborate tree structure. - - We can now define translators more precisely. A GlusterFS translator -is a shared object (`.so') that implements every filesystem call. -GlusterFS translators can be arranged in an arbitrary tree structure -(subject to constraints imposed by the translators). When GlusterFS -receives a filesystem call, it passes it on to the translator at the -root of the translator tree. The root translator may in turn pass it on -to any or all of its children, and so on, until the leaf nodes are -reached. The result of a filesystem call is communicated in the reverse -fashion, from the leaf nodes up to the root node, and then on to the -application. - - So what might a translator tree look like? - - - Fig 2. A sample translator tree - - The diagram depicts three servers and one GlusterFS client. It is -important to note that conceptually, the translator tree spans machine -boundaries. Thus, the client machine in the diagram, `10.0.0.1', can -access the aggregated storage of the filesystems on the server machines -`10.0.0.2', `10.0.0.3', and `10.0.0.4'. The translator diagram will -make more sense once you've read the next chapter and understood the -functions of the various translators. - - -File: user-guide.info, Node: Volume specification file, Prev: Translator, Up: Concepts - -3.3 Volume specification file -============================= - -The volume specification file describes the translator tree for both the -server and client programs. - - A volume specification file is a sequence of volume definitions. -The syntax of a volume definition is explained below: - - *volume* _volume-name_ - *type* _translator-name_ - *option* _option-name_ _option-value_ - ... - *subvolumes* _subvolume1_ _subvolume2_ ... - *end-volume* - - ... - -_volume-name_ - An identifier for the volume. This is just a human-readable name, - and can contain any alphanumeric character. For instance, - "storage-1", "colon-o", or "forty-two". - -_translator-name_ - Name of one of the available translators. Example: - `protocol/client', `cluster/unify'. - -_option-name_ - Name of a valid option for the translator. - -_option-value_ - Value for the option. Everything following the "option" keyword to - the end of the line is considered the value; it is up to the - translator to parse it. - -_subvolume1_, _subvolume2_, ... - Volume names of sub-volumes. The sub-volumes must already have - been defined earlier in the file. - - There are a few rules you must follow when writing a volume -specification file: - - * Everything following a ``#'' is considered a comment and is - ignored. Blank lines are also ignored. - - * All names and keywords are case-sensitive. - - * The order of options inside a volume definition does not matter. - - * An option value may not span multiple lines. - - * If an option is not specified, it will assume its default value. - - * A sub-volume must have already been defined before it can be - referenced. This means you have to write the specification file - "bottom-up", starting from the leaf nodes of the translator tree - and moving up to the root. - - A simple example volume specification file is shown below: - - # This is a comment line - volume client - type protocol/client - option transport-type tcp - option remote-host localhost # Also a comment - option remote-subvolume brick - # The subvolumes line may be absent - end-volume - - volume iot - type performance/io-threads - option thread-count 4 - subvolumes client - end-volume - - volume wb - type performance/write-behind - subvolumes iot - end-volume - - -File: user-guide.info, Node: Translators, Next: Usage Scenarios, Prev: Concepts, Up: Top - -4 Translators -************* - -* Menu: - -* Storage Translators:: -* Client and Server Translators:: -* Clustering Translators:: -* Performance Translators:: -* Features Translators:: -* Miscellaneous Translators:: - - This chapter documents all the available GlusterFS translators in -detail. Each translator section will show its name (for example, -`cluster/unify'), briefly describe its purpose and workings, and list -every option accepted by that translator and their meaning. - - -File: user-guide.info, Node: Storage Translators, Next: Client and Server Translators, Up: Translators - -4.1 Storage Translators -======================= - -The storage translators form the "backend" for GlusterFS. Currently, -the only available storage translator is the POSIX translator, which -stores files on a normal POSIX filesystem. A pleasant consequence of -this is that your data will still be accessible if GlusterFS crashes or -cannot be started. - - Other storage backends are planned for the future. One of the -possibilities is an Amazon S3 translator. Amazon S3 is an unlimited -online storage service accessible through a web services API. The S3 -translator will allow you to access the storage as a normal POSIX -filesystem. (1) - -* Menu: - -* POSIX:: -* BDB:: - - ---------- Footnotes ---------- - - (1) Some more discussion about this can be found at: - -http://developer.amazonwebservices.com/connect/message.jspa?messageID=52873 - - -File: user-guide.info, Node: POSIX, Next: BDB, Up: Storage Translators - -4.1.1 POSIX ------------ - - type storage/posix - - The `posix' translator uses a normal POSIX filesystem as its -"backend" to actually store files and directories. This can be any -filesystem that supports extended attributes (EXT3, ReiserFS, XFS, -...). Extended attributes are used by some translators to store -metadata, for example, by the replicate and stripe translators. See -*note Replicate:: and *note Stripe::, respectively for details. - -`directory <path>' - The directory on the local filesystem which is to be used for - storage. - - -File: user-guide.info, Node: BDB, Prev: POSIX, Up: Storage Translators - -4.1.2 BDB ---------- - - type storage/bdb - - The `BDB' translator uses a Berkeley DB database as its "backend" to -actually store files as key-value pair in the database and directories -as regular POSIX directories. Note that BDB does not provide extended -attribute support for regular files. Do not use BDB as storage -translator while using any translator that demands extended attributes -on "backend". - -`directory <path>' - The directory on the local filesystem which is to be used for - storage. - -`mode [cache|persistent] (cache)' - When BDB is run in `cache' mode, recovery of back-end is not - completely guaranteed. `persistent' guarantees that BDB can - recover back-end from Berkeley DB even if GlusterFS crashes. - -`errfile <path>' - The path of the file to be used as `errfile' for Berkeley DB to - report detailed error messages, if any. Note that all the contents - of this file will be written by Berkeley DB, not GlusterFS. - -`logdir <path>' - - -File: user-guide.info, Node: Client and Server Translators, Next: Clustering Translators, Prev: Storage Translators, Up: Translators - -4.2 Client and Server Translators -================================= - -The client and server translator enable GlusterFS to export a -translator tree over the network or access a remote GlusterFS server. -These two translators implement GlusterFS's network protocol. - -* Menu: - -* Transport modules:: -* Client protocol:: -* Server protocol:: - - -File: user-guide.info, Node: Transport modules, Next: Client protocol, Up: Client and Server Translators - -4.2.1 Transport modules ------------------------ - -The client and server translators are capable of using any of the -pluggable transport modules. Currently available transport modules are -`tcp', which uses a TCP connection between client and server to -communicate; `ib-sdp', which uses a TCP connection over InfiniBand, and -`ibverbs', which uses high-speed InfiniBand connections. - - Each transport module comes in two different versions, one to be -used on the server side and the other on the client side. - -4.2.1.1 TCP -........... - -The TCP transport module uses a TCP/IP connection between the server -and the client. - - option transport-type tcp - - The TCP client module accepts the following options: - -`non-blocking-connect [no|off|on|yes] (on)' - Whether to make the connection attempt asynchronous. - -`remote-port <n> (24007)' - Server port to connect to. - -`remote-host <hostname> *' - Hostname or IP address of the server. If the host name resolves to - multiple IP addresses, all of them will be tried in a round-robin - fashion. This feature can be used to implement fail-over. - - The TCP server module accepts the following options: - -`bind-address <address> (0.0.0.0)' - The local interface on which the server should listen to requests. - Default is to listen on all interfaces. - -`listen-port <n> (24007)' - The local port to listen on. - -4.2.1.2 IB-SDP -.............. - - option transport-type ib-sdp - - kernel implements socket interface for ib hardware. SDP is over -ib-verbs. This module accepts the same options as `tcp' - -4.2.1.3 ibverbs -............... - - option transport-type tcp - - InfiniBand is a scalable switched fabric interconnect mechanism -primarily used in high-performance computing. InfiniBand can deliver -data throughput of the order of 10 Gbit/s, with latencies of 4-5 ms. - - The `ib-verbs' transport accesses the InfiniBand hardware through -the "verbs" API, which is the lowest level of software access possible -and which gives the highest performance. On InfiniBand hardware, it is -always best to use `ib-verbs'. Use `ib-sdp' only if you cannot get -`ib-verbs' working for some reason. - - The `ib-verbs' client module accepts the following options: - -`non-blocking-connect [no|off|on|yes] (on)' - Whether to make the connection attempt asynchronous. - -`remote-port <n> (24007)' - Server port to connect to. - -`remote-host <hostname> *' - Hostname or IP address of the server. If the host name resolves to - multiple IP addresses, all of them will be tried in a round-robin - fashion. This feature can be used to implement fail-over. - - The `ib-verbs' server module accepts the following options: - -`bind-address <address> (0.0.0.0)' - The local interface on which the server should listen to requests. - Default is to listen on all interfaces. - -`listen-port <n> (24007)' - The local port to listen on. - - The following options are common to both the client and server -modules: - - If you are familiar with InfiniBand jargon, the mode is used by -GlusterFS is "reliable connection-oriented channel transfer". - -`ib-verbs-work-request-send-count <n> (64)' - Length of the send queue in datagrams. [Reason to - increase/decrease?] - -`ib-verbs-work-request-recv-count <n> (64)' - Length of the receive queue in datagrams. [Reason to - increase/decrease?] - -`ib-verbs-work-request-send-size <size> (128KB)' - Size of each datagram that is sent. [Reason to increase/decrease?] - -`ib-verbs-work-request-recv-size <size> (128KB)' - Size of each datagram that is received. [Reason to - increase/decrease?] - -`ib-verbs-port <n> (1)' - Port number for ib-verbs. - -`ib-verbs-mtu [256|512|1024|2048|4096] (2048)' - The Maximum Transmission Unit [Reason to increase/decrease?] - -`ib-verbs-device-name <device-name> (first device in the list)' - InfiniBand device to be used. - - For maximum performance, you should ensure that the send/receive -counts on both the client and server are the same. - - ib-verbs is preferred over ib-sdp. - - -File: user-guide.info, Node: Client protocol, Next: Server protocol, Prev: Transport modules, Up: Client and Server Translators - -4.2.2 Client ------------- - - type procotol/client - - The client translator enables the GlusterFS client to access a -remote server's translator tree. - -`transport-type [tcp,ib-sdp,ib-verbs] (tcp)' - The transport type to use. You should use the client versions of - all the transport modules (`tcp', `ib-sdp', `ib-verbs'). - -`remote-subvolume <volume_name> *' - The name of the volume on the remote host to attach to. Note that - this is _not_ the name of the `protocol/server' volume on the - server. It should be any volume under the server. - -`transport-timeout <n> (120- seconds)' - Inactivity timeout. If a reply is expected and no activity takes - place on the connection within this time, the transport connection - will be broken, and a new connection will be attempted. - - -File: user-guide.info, Node: Server protocol, Prev: Client protocol, Up: Client and Server Translators - -4.2.3 Server ------------- - - type protocol/server - - The server translator exports a translator tree and makes it -accessible to remote GlusterFS clients. - -`client-volume-filename <path> (<CONFDIR>/glusterfs-client.vol)' - The volume specification file to use for the client. This is the - file the client will receive when it is invoked with the - `--server' option (*note Client::). - -`transport-type [tcp,ib-verbs,ib-sdp] (tcp)' - The transport to use. You should use the server versions of all - the transport modules (`tcp', `ib-sdp', `ib-verbs'). - -`auth.addr.<volume name>.allow <IP address wildcard pattern>' - IP addresses of the clients that are allowed to attach to the - specified volume. This can be a wildcard. For example, a wildcard - of the form `192.168.*.*' allows any host in the `192.168.x.x' - subnet to connect to the server. - - - -File: user-guide.info, Node: Clustering Translators, Next: Performance Translators, Prev: Client and Server Translators, Up: Translators - -4.3 Clustering Translators -========================== - -The clustering translators are the most important GlusterFS -translators, since it is these that make GlusterFS a cluster -filesystem. These translators together enable GlusterFS to access an -arbitrarily large amount of storage, and provide RAID-like redundancy -and distribution over the entire cluster. - - There are three clustering translators: *unify*, *replicate*, and -*stripe*. The unify translator aggregates storage from many server -nodes. The replicate translator provides file replication. The stripe -translator allows a file to be spread across many server nodes. The -following sections look at each of these translators in detail. - -* Menu: - -* Unify:: -* Replicate:: -* Stripe:: - - -File: user-guide.info, Node: Unify, Next: Replicate, Up: Clustering Translators - -4.3.1 Unify ------------ - - type cluster/unify - - The unify translator presents a `unified' view of all its -sub-volumes. That is, it makes the union of all its sub-volumes appear -as a single volume. It is the unify translator that gives GlusterFS the -ability to access an arbitrarily large amount of storage. - - For unify to work correctly, certain invariants need to be -maintained across the entire network. These are: - - * The directory structure of all the sub-volumes must be identical. - - * A particular file can exist on only one of the sub-volumes. - Phrasing it in another way, a pathname such as - `/home/calvin/homework.txt') is unique across the entire cluster. - - - -Looking at the second requirement, you might wonder how one can -accomplish storing redundant copies of a file, if no file can exist -multiple times. To answer, we must remember that these invariants are -from _unify's perspective_. A translator such as replicate at a lower -level in the translator tree than unify may subvert this picture. - - The first invariant might seem quite tedious to ensure. We shall see -later that this is not so, since unify's _self-heal_ mechanism takes -care of maintaining it. - - The second invariant implies that unify needs some way to decide -which file goes where. Unify makes use of _scheduler_ modules for this -purpose. - - When a file needs to be created, unify's scheduler decides upon the -sub-volume to be used to store the file. There are many schedulers -available, each using a different algorithm and suitable for different -purposes. - - The various schedulers are described in detail in the sections that -follow. - -4.3.1.1 ALU -........... - - option scheduler alu - - ALU stands for "Adaptive Least Usage". It is the most advanced -scheduler available in GlusterFS. It balances the load across volumes -taking several factors in account. It adapts itself to changing I/O -patterns according to its configuration. When properly configured, it -can eliminate the need for regular tuning of the filesystem to keep -volume load nicely balanced. - - The ALU scheduler is composed of multiple least-usage -sub-schedulers. Each sub-scheduler keeps track of a certain type of -load, for each of the sub-volumes, getting statistics from the -sub-volumes themselves. The sub-schedulers are these: - - * disk-usage: The used and free disk space on the volume. - - * read-usage: The amount of reading done from this volume. - - * write-usage: The amount of writing done to this volume. - - * open-files-usage: The number of files currently open from this - volume. - - * disk-speed-usage: The speed at which the disks are spinning. This - is a constant value and therefore not very useful. - - The ALU scheduler needs to know which of these sub-schedulers to use, -and in which order to evaluate them. This is done through the `option -alu.order' configuration directive. - - Each sub-scheduler needs to know two things: when to kick in (the -entry-threshold), and how long to stay in control (the exit-threshold). -For example: when unifying three disks of 100GB, keeping an exact -balance of disk-usage is not necesary. Instead, there could be a 1GB -margin, which can be used to nicely balance other factors, such as -read-usage. The disk-usage scheduler can be told to kick in only when a -certain threshold of discrepancy is passed, such as 1GB. When it -assumes control under this condition, it will write all subsequent data -to the least-used volume. If it is doing so, it is unwise to stop right -after the values are below the entry-threshold again, since that would -make it very likely that the situation will occur again very soon. Such -a situation would cause the ALU to spend most of its time disk-usage -scheduling, which is unfair to the other sub-schedulers. The -exit-threshold therefore defines the amount of data that needs to be -written to the least-used disk, before control is relinquished again. - - In addition to the sub-schedulers, the ALU scheduler also has -"limits" options. These can stop the creation of new files on a volume -once values drop below a certain threshold. For example, setting -`option alu.limits.min-free-disk 5GB' will stop the scheduling of files -to volumes that have less than 5GB of free disk space, leaving the -files on that disk some room to grow. - - The actual values you assign to the thresholds for sub-schedulers and -limits depend on your situation. If you have fast-growing files, you'll -want to stop file-creation on a disk much earlier than when hardly any -of your files are growing. If you care less about disk-usage balance -than about read-usage balance, you'll want a bigger disk-usage -scheduler entry-threshold and a smaller read-usage scheduler -entry-threshold. - - For thresholds defining a size, values specifying "KB", "MB" and "GB" -are allowed. For example: `option alu.limits.min-free-disk 5GB'. - -`alu.order <order> * ("disk-usage:write-usage:read-usage:open-files-usage:disk-speed")' - -`alu.disk-usage.entry-threshold <size> (1GB)' - -`alu.disk-usage.exit-threshold <size> (512MB)' - -`alu.write-usage.entry-threshold <%> (25)' - -`alu.write-usage.exit-threshold <%> (5)' - -`alu.read-usage.entry-threshold <%> (25)' - -`alu.read-usage.exit-threshold <%> (5)' - -`alu.open-files-usage.entry-threshold <n> (1000)' - -`alu.open-files-usage.exit-threshold <n> (100)' - -`alu.limits.min-free-disk <%>' - -`alu.limits.max-open-files <n>' - -4.3.1.2 Round Robin (RR) -........................ - - option scheduler rr - - Round-Robin (RR) scheduler creates files in a round-robin fashion. -Each client will have its own round-robin loop. When your files are -mostly similar in size and I/O access pattern, this scheduler is a good -choice. RR scheduler checks for free disk space on the server before -scheduling, so you can know when to add another server node. The -default value of min-free-disk is 5% and is checked on file creation -calls, with atleast 10 seconds (by default) elapsing between two checks. - - Options: -`rr.limits.min-free-disk <%> (5)' - Minimum free disk space a node must have for RR to schedule a file - to it. - -`rr.refresh-interval <t> (10 seconds)' - Time between two successive free disk space checks. - -4.3.1.3 Random -.............. - - option scheduler random - - The random scheduler schedules file creation randomly among its -child nodes. Like the round-robin scheduler, it also checks for a -minimum amount of free disk space before scheduling a file to a node. - -`random.limits.min-free-disk <%> (5)' - Minimum free disk space a node must have for random to schedule a - file to it. - -`random.refresh-interval <t> (10 seconds)' - Time between two successive free disk space checks. - -4.3.1.4 NUFA -............ - - option scheduler nufa - - It is common in many GlusterFS computing environments for all -deployed machines to act as both servers and clients. For example, a -research lab may have 40 workstations each with its own storage. All of -these workstations might act as servers exporting a volume as well as -clients accessing the entire cluster's storage. In such a situation, -it makes sense to store locally created files on the local workstation -itself (assuming files are accessed most by the workstation that -created them). The Non-Uniform File Allocation (NUFA) scheduler -accomplishes that. - - NUFA gives the local system first priority for file creation over -other nodes. If the local volume does not have more free disk space -than a specified amount (5% by default) then NUFA schedules files among -the other child volumes in a round-robin fashion. - - NUFA is named after the similar strategy used for memory access, -NUMA(1). - -`nufa.limits.min-free-disk <%> (5)' - Minimum disk space that must be free (local or remote) for NUFA to - schedule a file to it. - -`nufa.refresh-interval <t> (10 seconds)' - Time between two successive free disk space checks. - -`nufa.local-volume-name <volume>' - The name of the volume corresponding to the local system. This - volume must be one of the children of the unify volume. This - option is mandatory. - -4.3.1.5 Namespace -................. - -Namespace volume needed because: - persistent inode numbers. - file -exists even when node is down. - - namespace files are simply touched. on every lookup it is checked. - -`namespace <volume> *' - Name of the namespace volume (which should be one of the unify - volume's children). - -`self-heal [on|off] (on)' - Enable/disable self-heal. Unless you know what you are doing, do - not disable self-heal. - -4.3.1.6 Self Heal -................. - -* When a 'lookup()/stat()' call is made on directory for the first -time, a self-heal call is made, which checks for the consistancy of its -child nodes. If an entry is present in storage node, but not in -namespace, that entry is created in namespace, and vica-versa. There is -an writedir() API introduced which is used for the same. It also checks -for permissions, and uid/gid consistencies. - - * This check is also done when an server goes down and comes up. - - * If one starts with an empty namespace export, but has data in -storage nodes, a 'find .>/dev/null' or 'ls -lR >/dev/null' should help -to build namespace in one shot. Even otherwise, namespace is built on -demand when a file is looked up for the first time. - - NOTE: There are some issues (Kernel 'Oops' msgs) seen with -fuse-2.6.3, when someone deletes namespace in backend, when glusterfs is -running. But with fuse-2.6.5, this issue is not there. - - ---------- Footnotes ---------- - - (1) Non-Uniform Memory Access: -<http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access> - - -File: user-guide.info, Node: Replicate, Next: Stripe, Prev: Unify, Up: Clustering Translators - -4.3.2 Replicate (formerly AFR) ------------------------------- - - type cluster/replicate - - Replicate provides RAID-1 like functionality for GlusterFS. -Replicate replicates files and directories across the subvolumes. Hence -if Replicate has four subvolumes, there will be four copies of all -files and directories. Replicate provides high-availability, i.e., in -case one of the subvolumes go down (e. g. server crash, network -disconnection) Replicate will still service the requests using the -redundant copies. - - Replicate also provides self-heal functionality, i.e., in case the -crashed servers come up, the outdated files and directories will be -updated with the latest versions. Replicate uses extended attributes of -the backend file system to track the versioning of files and -directories and provide the self-heal feature. - - volume replicate-example - type cluster/replicate - subvolumes brick1 brick2 brick3 - end-volume - - This sample configuration will replicate all directories and files on -brick1, brick2 and brick3. - - All the read operations happen from the first alive child. If all the -three sub-volumes are up, reads will be done from brick1; if brick1 is -down read will be done from brick2. In case read() was being done on -brick1 and it goes down, replicate transparently falls back to brick2. - - The next release of GlusterFS will add the following features: - * Ability to specify the sub-volume from which read operations are - to be done (this will help users who have one of the sub-volumes - as a local storage volume). - - * Allow scheduling of read operations amongst the sub-volumes in a - round-robin fashion. - - The order of the subvolumes list should be same across all the -'replicate's as they will be used for locking purposes. - -4.3.2.1 Self Heal -................. - -Replicate has self-heal feature, which updates the outdated file and -directory copies by the most recent versions. For example consider the -following config: - - volume replicate-example - type cluster/replicate - subvolumes brick1 brick2 - end-volume - -4.3.2.2 File self-heal -...................... - -Now if we create a file foo.txt on replicate-example, the file will be -created on brick1 and brick2. The file will have two extended -attributes associated with it in the backend filesystem. One is -trusted.afr.createtime and the other is trusted.afr.version. The -trusted.afr.createtime xattr has the create time (in terms of seconds -since epoch) and trusted.afr.version is a number that is incremented -each time a file is modified. This increment happens during close -(incase any write was done before close). - - If brick1 goes down, we edit foo.txt the version gets incremented. -Now the brick1 comes back up, when we open() on foo.txt replicate will -check if their versions are same. If they are not same, the outdated -copy is replaced by the latest copy and its version is updated. After -the sync the open() proceeds in the usual manner and the application -calling open() can continue on its access to the file. - - If brick1 goes down, we delete foo.txt and create a file with the -same name again i.e foo.txt. Now brick1 comes back up, clearly there is -a chance that the version on brick1 being more than the version on -brick2, this is where createtime extended attribute helps in deciding -which the outdated copy is. Hence we need to consider both createtime -and version to decide on the latest copy. - - The version attribute is incremented during the close() call. Version -will not be incremented in case there was no write() done. In case the -fd that the close() gets was got by create() call, we also create the -createtime extended attribute. - -4.3.2.3 Directory self-heal -........................... - -Suppose brick1 goes down, we delete foo.txt, brick1 comes back up, now -we should not create foo.txt on brick2 but we should delete foo.txt on -brick1. We handle this situation by having the createtime and version -attribute on the directory similar to the file. when lookup() is done -on the directory, we compare the createtime/version attributes of the -copies and see which files needs to be deleted and delete those files -and update the extended attributes of the outdated directory copy. -Each time a directory is modified (a file or a subdirectory is created -or deleted inside the directory) and one of the subvols is down, we -increment the directory's version. - - lookup() is a call initiated by the kernel on a file or directory -just before any access to that file or directory. In glusterfs, by -default, lookup() will not be called in case it was called in the past -one second on that particular file or directory. - - The extended attributes can be seen in the backend filesystem using -the `getfattr' command. (`getfattr -n trusted.afr.version <file>') - -`debug [on|off] (off)' - -`self-heal [on|off] (on)' - -`replicate <pattern> (*:1)' - -`lock-node <child_volume> (first child is used by default)' - - -File: user-guide.info, Node: Stripe, Prev: Replicate, Up: Clustering Translators - -4.3.3 Stripe ------------- - - type cluster/stripe - - The stripe translator distributes the contents of a file over its -sub-volumes. It does this by creating a file equal in size to the -total size of the file on each of its sub-volumes. It then writes only -a part of the file to each sub-volume, leaving the rest of it empty. -These empty regions are called `holes' in Unix terminology. The holes -do not consume any disk space. - - The diagram below makes this clear. - - - -You can configure stripe so that only filenames matching a pattern are -striped. You can also configure the size of the data to be stored on -each sub-volume. - -`block-size <pattern>:<size> (*:0 no striping)' - Distribute files matching `<pattern>' over the sub-volumes, - storing at least `<size>' on each sub-volume. For example, - - option block-size *.mpg:1M - - distributes all files ending in `.mpg', storing at least 1 MB on - each sub-volume. - - Any number of `block-size' option lines may be present, specifying - different sizes for different file name patterns. - - -File: user-guide.info, Node: Performance Translators, Next: Features Translators, Prev: Clustering Translators, Up: Translators - -4.4 Performance Translators -=========================== - -* Menu: - -* Read Ahead:: -* Write Behind:: -* IO Threads:: -* IO Cache:: -* Booster:: - - -File: user-guide.info, Node: Read Ahead, Next: Write Behind, Up: Performance Translators - -4.4.1 Read Ahead ----------------- - - type performance/read-ahead - - The read-ahead translator pre-fetches data in advance on every read. -This benefits applications that mostly process files in sequential -order, since the next block of data will already be available by the -time the application is done with the current one. - - Additionally, the read-ahead translator also behaves as a -read-aggregator. Many small read operations are combined and issued as -fewer, larger read requests to the server. - - Read-ahead deals in "pages" as the unit of data fetched. The page -size is configurable, as is the "page count", which is the number of -pages that are pre-fetched. - - Read-ahead is best used with InfiniBand (using the ib-verbs -transport). On FastEthernet and Gigabit Ethernet networks, GlusterFS -can achieve the link-maximum throughput even without read-ahead, making -it quite superflous. - - Note that read-ahead only happens if the reads are perfectly -sequential. If your application accesses data in a random fashion, -using read-ahead might actually lead to a performance loss, since -read-ahead will pointlessly fetch pages which won't be used by the -application. - - Options: -`page-size <n> (256KB)' - The unit of data that is pre-fetched. - -`page-count <n> (2)' - The number of pages that are pre-fetched. - -`force-atime-update [on|off|yes|no] (off|no)' - Whether to force an access time (atime) update on the file on - every read. Without this, the atime will be slightly imprecise, as - it will reflect the time when the read-ahead translator read the - data, not when the application actually read it. - - -File: user-guide.info, Node: Write Behind, Next: IO Threads, Prev: Read Ahead, Up: Performance Translators - -4.4.2 Write Behind ------------------- - - type performance/write-behind - - The write-behind translator improves the latency of a write -operation. It does this by relegating the write operation to the -background and returning to the application even as the write is in -progress. Using the write-behind translator, successive write requests -can be pipelined. This mode of write-behind operation is best used on -the client side, to enable decreased write latency for the application. - - The write-behind translator can also aggregate write requests. If the -`aggregate-size' option is specified, then successive writes upto that -size are accumulated and written in a single operation. This mode of -operation is best used on the server side, as this will decrease the -disk's head movement when multiple files are being written to in -parallel. - - The `aggregate-size' option has a default value of 128KB. Although -this works well for most users, you should always experiment with -different values to determine the one that will deliver maximum -performance. This is because the performance of write-behind depends on -your interconnect, size of RAM, and the work load. - -`aggregate-size <n> (128KB)' - Amount of data to accumulate before doing a write - -`flush-behind [on|yes|off|no] (off|no)' - - -File: user-guide.info, Node: IO Threads, Next: IO Cache, Prev: Write Behind, Up: Performance Translators - -4.4.3 IO Threads ----------------- - - type performance/io-threads - - The IO threads translator is intended to increase the responsiveness -of the server to metadata operations by doing file I/O (read, write) in -a background thread. Since the GlusterFS server is single-threaded, -using the IO threads translator can significantly improve performance. -This translator is best used on the server side, loaded just below the -server protocol translator. - - IO threads operates by handing out read and write requests to a -separate thread. The total number of threads in existence at a time is -constant, and configurable. - -`thread-count <n> (1)' - Number of threads to use. - - -File: user-guide.info, Node: IO Cache, Next: Booster, Prev: IO Threads, Up: Performance Translators - -4.4.4 IO Cache --------------- - - type performance/io-cache - - The IO cache translator caches data that has been read. This is -useful if many applications read the same data multiple times, and if -reads are much more frequent than writes (for example, IO caching may be -useful in a web hosting environment, where most clients will simply -read some files and only a few will write to them). - - The IO cache translator reads data from its child in `page-size' -chunks. It caches data upto `cache-size' bytes. The cache is -maintained as a prioritized least-recently-used (LRU) list, with -priorities determined by user-specified patterns to match filenames. - - When the IO cache translator detects a write operation, the cache -for that file is flushed. - - The IO cache translator periodically verifies the consistency of -cached data, using the modification times on the files. The -verification timeout is configurable. - -`page-size <n> (128KB)' - Size of a page. - -`cache-size (n) (32MB)' - Total amount of data to be cached. - -`force-revalidate-timeout <n> (1)' - Timeout to force a cache consistency verification, in seconds. - -`priority <pattern> (*:0)' - Filename patterns listed in order of priority. - - -File: user-guide.info, Node: Booster, Prev: IO Cache, Up: Performance Translators - -4.4.5 Booster -------------- - - type performance/booster - - The booster translator gives applications a faster path to -communicate read and write requests to GlusterFS. Normally, all -requests to GlusterFS from applications go through FUSE, as indicated -in *note Filesystems in Userspace::. Using the booster translator in -conjunction with the GlusterFS booster shared library, an application -can bypass the FUSE path and send read/write requests directly to the -GlusterFS client process. - - The booster mechanism consists of two parts: the booster translator, -and the booster shared library. The booster translator is meant to be -loaded on the client side, usually at the root of the translator tree. -The booster shared library should be `LD_PRELOAD'ed with the -application. - - The booster translator when loaded opens a Unix domain socket and -listens for read/write requests on it. The booster shared library -intercepts read and write system calls and sends the requests to the -GlusterFS process directly using the Unix domain socket, bypassing FUSE. -This leads to superior performance. - - Once you've loaded the booster translator in your volume -specification file, you can start your application as: - - $ LD_PRELOAD=/usr/local/bin/glusterfs-booster.so your_app - - The booster translator accepts no options. - - -File: user-guide.info, Node: Features Translators, Next: Miscellaneous Translators, Prev: Performance Translators, Up: Translators - -4.5 Features Translators -======================== - -* Menu: - -* POSIX Locks:: -* Fixed ID:: - - -File: user-guide.info, Node: POSIX Locks, Next: Fixed ID, Up: Features Translators - -4.5.1 POSIX Locks ------------------ - - type features/posix-locks - - This translator provides storage independent POSIX record locking -support (`fcntl' locking). Typically you'll want to load this on the -server side, just above the POSIX storage translator. Using this -translator you can get both advisory locking and mandatory locking -support. It also handles `flock()' locks properly. - - Caveat: Consider a file that does not have its mandatory locking bits -(+setgid, -group execution) turned on. Assume that this file is now -opened by a process on a client that has the write-behind xlator -loaded. The write-behind xlator does not cache anything for files which -have mandatory locking enabled, to avoid incoherence. Let's say that -mandatory locking is now enabled on this file through another client. -The former client will not know about this change, and write-behind may -erroneously report a write as being successful when in fact it would -fail due to the region it is writing to being locked. - - There seems to be no easy way to fix this. To work around this -problem, it is recommended that you never enable the mandatory bits on -a file while it is open. - -`mandatory [on|off] (on)' - Turns mandatory locking on. - - -File: user-guide.info, Node: Fixed ID, Prev: POSIX Locks, Up: Features Translators - -4.5.2 Fixed ID --------------- - - type features/fixed-id - - The fixed ID translator makes all filesystem requests from the client -to appear to be coming from a fixed, specified UID/GID, regardless of -which user actually initiated the request. - -`fixed-uid <n> [if not set, not used]' - The UID to send to the server - -`fixed-gid <n> [if not set, not used]' - The GID to send to the server - - -File: user-guide.info, Node: Miscellaneous Translators, Prev: Features Translators, Up: Translators - -4.6 Miscellaneous Translators -============================= - -* Menu: - -* ROT-13:: -* Trace:: - - -File: user-guide.info, Node: ROT-13, Next: Trace, Up: Miscellaneous Translators - -4.6.1 ROT-13 ------------- - - type encryption/rot-13 - - ROT-13 is a toy translator that can "encrypt" and "decrypt" file -contents using the ROT-13 algorithm. ROT-13 is a trivial algorithm that -rotates each alphabet by thirteen places. Thus, 'A' becomes 'N', 'B' -becomes 'O', and 'Z' becomes 'M'. - - It goes without saying that you shouldn't use this translator if you -need _real_ encryption (a future release of GlusterFS will have real -encryption translators). - -`encrypt-write [on|off] (on)' - Whether to encrypt on write - -`decrypt-read [on|off] (on)' - Whether to decrypt on read - - -File: user-guide.info, Node: Trace, Prev: ROT-13, Up: Miscellaneous Translators - -4.6.2 Trace ------------ - - type debug/trace - - The trace translator is intended for debugging purposes. When -loaded, it logs all the system calls received by the server or client -(wherever trace is loaded), their arguments, and the results. You must -use a GlusterFS log level of DEBUG (See *note Running GlusterFS::) for -trace to work. - - Sample trace output (lines have been wrapped for readability): - 2007-10-30 00:08:58 D [trace.c:1579:trace_opendir] trace: callid: 68 - (*this=0x8059e40, loc=0x8091984 {path=/iozone3_283, inode=0x8091f00}, - fd=0x8091d50) - - 2007-10-30 00:08:58 D [trace.c:630:trace_opendir_cbk] trace: - (*this=0x8059e40, op_ret=4, op_errno=1, fd=0x8091d50) - - 2007-10-30 00:08:58 D [trace.c:1602:trace_readdir] trace: callid: 69 - (*this=0x8059e40, size=4096, offset=0 fd=0x8091d50) - - 2007-10-30 00:08:58 D [trace.c:215:trace_readdir_cbk] trace: - (*this=0x8059e40, op_ret=0, op_errno=0, count=4) - - 2007-10-30 00:08:58 D [trace.c:1624:trace_closedir] trace: callid: 71 - (*this=0x8059e40, *fd=0x8091d50) - - 2007-10-30 00:08:58 D [trace.c:809:trace_closedir_cbk] trace: - (*this=0x8059e40, op_ret=0, op_errno=1) - - -File: user-guide.info, Node: Usage Scenarios, Next: Troubleshooting, Prev: Translators, Up: Top - -5 Usage Scenarios -***************** - -5.1 Advanced Striping -===================== - -This section is based on the Advanced Striping tutorial written by -Anand Avati on the GlusterFS wiki (1). - -5.1.1 Mixed Storage Requirements --------------------------------- - -There are two ways of scheduling the I/O. One at file level (using -unify translator) and other at block level (using stripe translator). -Striped I/O is good for files that are potentially large and require -high parallel throughput (for example, a single file of 400GB being -accessed by 100s and 1000s of systems simultaneously and randomly). For -most of the cases, file level scheduling works best. - - In the real world, it is desirable to mix file level and block level -scheduling on a single storage volume. Alternatively users can choose -to have two separate volumes and hence two mount points, but the -applications may demand a single storage system to host both. - - This document explains how to mix file level scheduling with stripe. - -5.1.2 Configuration Brief -------------------------- - -This setup demonstrates how users can configure unify translator with -appropriate I/O scheduler for file level scheduling and strip for only -matching patterns. This way, GlusterFS chooses appropriate I/O profile -and knows how to efficiently handle both the types of data. - - A simple technique to achieve this effect is to create a stripe set -of unify and stripe blocks, where unify is the first sub-volume. Files -that do not match the stripe policy passed on to first unify sub-volume -and inturn scheduled arcoss the cluster using its file level I/O -scheduler. - - 5.1.3 Preparing GlusterFS Envoronment -------------------------------------- - -Create the directories /export/namespace, /export/unify and -/export/stripe on all the storage bricks. - - Place the following server and client volume spec file under -/etc/glusterfs (or appropriate installed path) and replace the IP -addresses / access control fields to match your environment. - - ## file: /etc/glusterfs/glusterfsd.vol - volume posix-unify - type storage/posix - option directory /export/for-unify - end-volume - - volume posix-stripe - type storage/posix - option directory /export/for-stripe - end-volume - - volume posix-namespace - type storage/posix - option directory /export/for-namespace - end-volume - - volume server - type protocol/server - option transport-type tcp - option auth.addr.posix-unify.allow 192.168.1.* - option auth.addr.posix-stripe.allow 192.168.1.* - option auth.addr.posix-namespace.allow 192.168.1.* - subvolumes posix-unify posix-stripe posix-namespace - end-volume - - ## file: /etc/glusterfs/glusterfs.vol - volume client-namespace - type protocol/client - option transport-type tcp - option remote-host 192.168.1.1 - option remote-subvolume posix-namespace - end-volume - - volume client-unify-1 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.1 - option remote-subvolume posix-unify - end-volume - - volume client-unify-2 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.2 - option remote-subvolume posix-unify - end-volume - - volume client-unify-3 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.3 - option remote-subvolume posix-unify - end-volume - - volume client-unify-4 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.4 - option remote-subvolume posix-unify - end-volume - - volume client-stripe-1 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.1 - option remote-subvolume posix-stripe - end-volume - - volume client-stripe-2 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.2 - option remote-subvolume posix-stripe - end-volume - - volume client-stripe-3 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.3 - option remote-subvolume posix-stripe - end-volume - - volume client-stripe-4 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.4 - option remote-subvolume posix-stripe - end-volume - - volume unify - type cluster/unify - option scheduler rr - subvolumes cluster-unify-1 cluster-unify-2 cluster-unify-3 cluster-unify-4 - end-volume - - volume stripe - type cluster/stripe - option block-size *.img:2MB # All files ending with .img are striped with 2MB stripe block size. - subvolumes unify cluster-stripe-1 cluster-stripe-2 cluster-stripe-3 cluster-stripe-4 - end-volume - - Bring up the Storage - - Starting GlusterFS Server: If you have installed through binary -package, you can start the service through init.d startup script. If -not: - - [root@server]# glusterfsd - - Mounting GlusterFS Volumes: - - [root@client]# glusterfs -s [BRICK-IP-ADDRESS] /mnt/cluster - - Improving upon this Setup - - Infiniband Verbs RDMA transport is much faster than TCP/IP GigE -transport. - - Use of performance translators such as read-ahead, write-behind, -io-cache, io-threads, booster is recommended. - - Replace round-robin (rr) scheduler with ALU to handle more dynamic -storage environments. - - ---------- Footnotes ---------- - - (1) -http://gluster.org/docs/index.php/Mixing_Striped_and_Regular_Files - - -File: user-guide.info, Node: Troubleshooting, Next: GNU Free Documentation Licence, Prev: Usage Scenarios, Up: Top - -6 Troubleshooting -***************** - -This chapter is a general troubleshooting guide to GlusterFS. It lists -common GlusterFS server and client error messages, debugging hints, and -concludes with the suggested procedure to report bugs in GlusterFS. - -6.1 GlusterFS error messages -============================ - -6.1.1 Server errors -------------------- - - glusterfsd: FATAL: could not open specfile: - '/etc/glusterfs/glusterfsd.vol' - - The GlusterFS server expects the volume specification file to be at -`/etc/glusterfs/glusterfsd.vol'. The example specification file will be -installed as `/etc/glusterfs/glusterfsd.vol.sample'. You need to edit -it and rename it, or provide a different specification file using the -`--spec-file' command line option (See *note Server::). - - gf_log_init: failed to open logfile "/usr/var/log/glusterfs/glusterfsd.log" - (Permission denied) - - You don't have permission to create files in the -`/usr/var/log/glusterfs' directory. Make sure you are running GlusterFS -as root. Alternatively, specify a different path for the log file using -the `--log-file' option (See *note Server::). - -6.1.2 Client errors -------------------- - - fusermount: failed to access mountpoint /mnt: - Transport endpoint is not connected - - A previous failed (or hung) mount of GlusterFS is preventing it from -being mounted again in the same location. The fix is to do: - - # umount /mnt - - and try mounting again. - - *"Transport endpoint is not connected".* - - If you get this error when you try a command such as `ls' or `cat', -it means the GlusterFS mount did not succeed. Try running GlusterFS in -`DEBUG' logging level and study the log messages to discover the cause. - - *"Connect to server failed", "SERVER-ADDRESS: Connection refused".* - - GluserFS Server is not running or dead. Check your network -connections and firewall settings. To check if the server is reachable, -try: - - telnet IP-ADDRESS 24007 - - If the server is accessible, your `telnet' command should connect and -block. If not you will see an error message such as `telnet: Unable to -connect to remote host: Connection refused'. 24007 is the default -GlusterFS port. If you have changed it, then use the corresponding port -instead. - - gf_log_init: failed to open logfile "/usr/var/log/glusterfs/glusterfs.log" - (Permission denied) - - You don't have permission to create files in the -`/usr/var/log/glusterfs' directory. Make sure you are running GlusterFS -as root. Alternatively, specify a different path for the log file using -the `--log-file' option (See *note Client::). - -6.2 FUSE error messages -======================= - -`modprobe fuse' fails with: "Unknown symbol in module, or unknown -parameter". - - If you are using fuse-2.6.x on Redhat Enterprise Linux Work Station 4 -and Advanced Server 4 with 2.6.9-42.ELlargesmp, 2.6.9-42.ELsmp, -2.6.9-42.EL kernels and get this error while loading FUSE kernel -module, you need to apply the following patch. - - For fuse-2.6.2: - -<http://ftp.gluster.com/pub/gluster/glusterfs/fuse/fuse-2.6.2-rhel-build.patch> - - For fuse-2.6.3: - -<http://ftp.gluster.com/pub/gluster/glusterfs/fuse/fuse-2.6.3-rhel-build.patch> - -6.3 AppArmour and GlusterFS -=========================== - -Under OpenSuSE GNU/Linux, the AppArmour security feature does not allow -GlusterFS to create temporary files or network socket connections even -while running as root. You will see error messages like `Unable to open -log file: Operation not permitted' or `Connection refused'. Disabling -AppArmour using YaST or properly configuring AppArmour to recognize -`glusterfsd' or `glusterfs'/`fusermount' should solve the problem. - -6.4 Reporting a bug -=================== - -If you encounter a bug in GlusterFS, please follow the below guidelines -when you report it to the mailing list. Be sure to report it! User -feedback is crucial to the health of the project and we value it highly. - -6.4.1 General instructions --------------------------- - -When running GlusterFS in a non-production environment, be sure to -build it with the following command: - - $ make CFLAGS='-g -O0 -DDEBUG' - - This includes debugging information which will be helpful in getting -backtraces (see below) and also disable optimization. Enabling -optimization can result in incorrect line numbers being reported to gdb. - -6.4.2 Volume specification files --------------------------------- - -Attach all relevant server and client spec files you were using when -you encountered the bug. Also tell us details of your setup, i.e., how -many clients and how many servers. - -6.4.3 Log files ---------------- - -Set the loglevel of your client and server programs to DEBUG (by -passing the -L DEBUG option) and attach the log files with your bug -report. Obviously, if only the client is failing (for example), you -only need to send us the client log file. - -6.4.4 Backtrace ---------------- - -If GlusterFS has encountered a segmentation fault or has crashed for -some other reason, include the backtrace with the bug report. You can -get the backtrace using the following procedure. - - Run the GlusterFS client or server inside gdb. - - $ gdb ./glusterfs - (gdb) set args -f client.spec -N -l/path/to/log/file -LDEBUG /mnt/point - (gdb) run - - Now when the process segfaults, you can get the backtrace by typing: - - (gdb) bt - - If the GlusterFS process has crashed and dumped a core file (you can -find this in / if running as a daemon and in the current directory -otherwise), you can do: - - $ gdb /path/to/glusterfs /path/to/core.<pid> - - and then get the backtrace. - - If the GlusterFS server or client seems to be hung, then you can get -the backtrace by attaching gdb to the process. First get the `PID' of -the process (using ps), and then do: - - $ gdb ./glusterfs <pid> - - Press Ctrl-C to interrupt the process and then generate the -backtrace. - -6.4.5 Reproducing the bug -------------------------- - -If the bug is reproducible, please include the steps necessary to do -so. If the bug is not reproducible, send us the bug report anyway. - -6.4.6 Other information ------------------------ - -If you think it is relevant, send us also the version of FUSE you're -using, the kernel version, platform. - - -File: user-guide.info, Node: GNU Free Documentation Licence, Next: Index, Prev: Troubleshooting, Up: Top - -Appendix A GNU Free Documentation Licence -***************************************** - - Version 1.2, November 2002 - - Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - 0. PREAMBLE - - The purpose of this License is to make a manual, textbook, or other - functional and useful document "free" in the sense of freedom: to - assure everyone the effective freedom to copy and redistribute it, - with or without modifying it, either commercially or - noncommercially. Secondarily, this License preserves for the - author and publisher a way to get credit for their work, while not - being considered responsible for modifications made by others. - - This License is a kind of "copyleft", which means that derivative - works of the document must themselves be free in the same sense. - It complements the GNU Affero General Public License, which is a copyleft - license designed for free software. - - We have designed this License in order to use it for manuals for - free software, because free software needs free documentation: a - free program should come with manuals providing the same freedoms - that the software does. But this License is not limited to - software manuals; it can be used for any textual work, regardless - of subject matter or whether it is published as a printed book. - We recommend this License principally for works whose purpose is - instruction or reference. - - 1. APPLICABILITY AND DEFINITIONS - - This License applies to any manual or other work, in any medium, - that contains a notice placed by the copyright holder saying it - can be distributed under the terms of this License. Such a notice - grants a world-wide, royalty-free license, unlimited in duration, - to use that work under the conditions stated herein. The - "Document", below, refers to any such manual or work. Any member - of the public is a licensee, and is addressed as "you". You - accept the license if you copy, modify or distribute the work in a - way requiring permission under copyright law. - - A "Modified Version" of the Document means any work containing the - Document or a portion of it, either copied verbatim, or with - modifications and/or translated into another language. - - A "Secondary Section" is a named appendix or a front-matter section - of the Document that deals exclusively with the relationship of the - publishers or authors of the Document to the Document's overall - subject (or to related matters) and contains nothing that could - fall directly within that overall subject. (Thus, if the Document - is in part a textbook of mathematics, a Secondary Section may not - explain any mathematics.) The relationship could be a matter of - historical connection with the subject or with related matters, or - of legal, commercial, philosophical, ethical or political position - regarding them. - - The "Invariant Sections" are certain Secondary Sections whose - titles are designated, as being those of Invariant Sections, in - the notice that says that the Document is released under this - License. If a section does not fit the above definition of - Secondary then it is not allowed to be designated as Invariant. - The Document may contain zero Invariant Sections. If the Document - does not identify any Invariant Sections then there are none. - - The "Cover Texts" are certain short passages of text that are - listed, as Front-Cover Texts or Back-Cover Texts, in the notice - that says that the Document is released under this License. A - Front-Cover Text may be at most 5 words, and a Back-Cover Text may - be at most 25 words. - - A "Transparent" copy of the Document means a machine-readable copy, - represented in a format whose specification is available to the - general public, that is suitable for revising the document - straightforwardly with generic text editors or (for images - composed of pixels) generic paint programs or (for drawings) some - widely available drawing editor, and that is suitable for input to - text formatters or for automatic translation to a variety of - formats suitable for input to text formatters. A copy made in an - otherwise Transparent file format whose markup, or absence of - markup, has been arranged to thwart or discourage subsequent - modification by readers is not Transparent. An image format is - not Transparent if used for any substantial amount of text. A - copy that is not "Transparent" is called "Opaque". - - Examples of suitable formats for Transparent copies include plain - ASCII without markup, Texinfo input format, LaTeX input format, - SGML or XML using a publicly available DTD, and - standard-conforming simple HTML, PostScript or PDF designed for - human modification. Examples of transparent image formats include - PNG, XCF and JPG. Opaque formats include proprietary formats that - can be read and edited only by proprietary word processors, SGML or - XML for which the DTD and/or processing tools are not generally - available, and the machine-generated HTML, PostScript or PDF - produced by some word processors for output purposes only. - - The "Title Page" means, for a printed book, the title page itself, - plus such following pages as are needed to hold, legibly, the - material this License requires to appear in the title page. For - works in formats which do not have any title page as such, "Title - Page" means the text near the most prominent appearance of the - work's title, preceding the beginning of the body of the text. - - A section "Entitled XYZ" means a named subunit of the Document - whose title either is precisely XYZ or contains XYZ in parentheses - following text that translates XYZ in another language. (Here XYZ - stands for a specific section name mentioned below, such as - "Acknowledgements", "Dedications", "Endorsements", or "History".) - To "Preserve the Title" of such a section when you modify the - Document means that it remains a section "Entitled XYZ" according - to this definition. - - The Document may include Warranty Disclaimers next to the notice - which states that this License applies to the Document. These - Warranty Disclaimers are considered to be included by reference in - this License, but only as regards disclaiming warranties: any other - implication that these Warranty Disclaimers may have is void and - has no effect on the meaning of this License. - - 2. VERBATIM COPYING - - You may copy and distribute the Document in any medium, either - commercially or noncommercially, provided that this License, the - copyright notices, and the license notice saying this License - applies to the Document are reproduced in all copies, and that you - add no other conditions whatsoever to those of this License. You - may not use technical measures to obstruct or control the reading - or further copying of the copies you make or distribute. However, - you may accept compensation in exchange for copies. If you - distribute a large enough number of copies you must also follow - the conditions in section 3. - - You may also lend copies, under the same conditions stated above, - and you may publicly display copies. - - 3. COPYING IN QUANTITY - - If you publish printed copies (or copies in media that commonly - have printed covers) of the Document, numbering more than 100, and - the Document's license notice requires Cover Texts, you must - enclose the copies in covers that carry, clearly and legibly, all - these Cover Texts: Front-Cover Texts on the front cover, and - Back-Cover Texts on the back cover. Both covers must also clearly - and legibly identify you as the publisher of these copies. The - front cover must present the full title with all words of the - title equally prominent and visible. You may add other material - on the covers in addition. Copying with changes limited to the - covers, as long as they preserve the title of the Document and - satisfy these conditions, can be treated as verbatim copying in - other respects. - - If the required texts for either cover are too voluminous to fit - legibly, you should put the first ones listed (as many as fit - reasonably) on the actual cover, and continue the rest onto - adjacent pages. - - If you publish or distribute Opaque copies of the Document - numbering more than 100, you must either include a - machine-readable Transparent copy along with each Opaque copy, or - state in or with each Opaque copy a computer-network location from - which the general network-using public has access to download - using public-standard network protocols a complete Transparent - copy of the Document, free of added material. If you use the - latter option, you must take reasonably prudent steps, when you - begin distribution of Opaque copies in quantity, to ensure that - this Transparent copy will remain thus accessible at the stated - location until at least one year after the last time you - distribute an Opaque copy (directly or through your agents or - retailers) of that edition to the public. - - It is requested, but not required, that you contact the authors of - the Document well before redistributing any large number of - copies, to give them a chance to provide you with an updated - version of the Document. - - 4. MODIFICATIONS - - You may copy and distribute a Modified Version of the Document - under the conditions of sections 2 and 3 above, provided that you - release the Modified Version under precisely this License, with - the Modified Version filling the role of the Document, thus - licensing distribution and modification of the Modified Version to - whoever possesses a copy of it. In addition, you must do these - things in the Modified Version: - - A. Use in the Title Page (and on the covers, if any) a title - distinct from that of the Document, and from those of - previous versions (which should, if there were any, be listed - in the History section of the Document). You may use the - same title as a previous version if the original publisher of - that version gives permission. - - B. List on the Title Page, as authors, one or more persons or - entities responsible for authorship of the modifications in - the Modified Version, together with at least five of the - principal authors of the Document (all of its principal - authors, if it has fewer than five), unless they release you - from this requirement. - - C. State on the Title page the name of the publisher of the - Modified Version, as the publisher. - - D. Preserve all the copyright notices of the Document. - - E. Add an appropriate copyright notice for your modifications - adjacent to the other copyright notices. - - F. Include, immediately after the copyright notices, a license - notice giving the public permission to use the Modified - Version under the terms of this License, in the form shown in - the Addendum below. - - G. Preserve in that license notice the full lists of Invariant - Sections and required Cover Texts given in the Document's - license notice. - - H. Include an unaltered copy of this License. - - I. Preserve the section Entitled "History", Preserve its Title, - and add to it an item stating at least the title, year, new - authors, and publisher of the Modified Version as given on - the Title Page. If there is no section Entitled "History" in - the Document, create one stating the title, year, authors, - and publisher of the Document as given on its Title Page, - then add an item describing the Modified Version as stated in - the previous sentence. - - J. Preserve the network location, if any, given in the Document - for public access to a Transparent copy of the Document, and - likewise the network locations given in the Document for - previous versions it was based on. These may be placed in - the "History" section. You may omit a network location for a - work that was published at least four years before the - Document itself, or if the original publisher of the version - it refers to gives permission. - - K. For any section Entitled "Acknowledgements" or "Dedications", - Preserve the Title of the section, and preserve in the - section all the substance and tone of each of the contributor - acknowledgements and/or dedications given therein. - - L. Preserve all the Invariant Sections of the Document, - unaltered in their text and in their titles. Section numbers - or the equivalent are not considered part of the section - titles. - - M. Delete any section Entitled "Endorsements". Such a section - may not be included in the Modified Version. - - N. Do not retitle any existing section to be Entitled - "Endorsements" or to conflict in title with any Invariant - Section. - - O. Preserve any Warranty Disclaimers. - - If the Modified Version includes new front-matter sections or - appendices that qualify as Secondary Sections and contain no - material copied from the Document, you may at your option - designate some or all of these sections as invariant. To do this, - add their titles to the list of Invariant Sections in the Modified - Version's license notice. These titles must be distinct from any - other section titles. - - You may add a section Entitled "Endorsements", provided it contains - nothing but endorsements of your Modified Version by various - parties--for example, statements of peer review or that the text - has been approved by an organization as the authoritative - definition of a standard. - - You may add a passage of up to five words as a Front-Cover Text, - and a passage of up to 25 words as a Back-Cover Text, to the end - of the list of Cover Texts in the Modified Version. Only one - passage of Front-Cover Text and one of Back-Cover Text may be - added by (or through arrangements made by) any one entity. If the - Document already includes a cover text for the same cover, - previously added by you or by arrangement made by the same entity - you are acting on behalf of, you may not add another; but you may - replace the old one, on explicit permission from the previous - publisher that added the old one. - - The author(s) and publisher(s) of the Document do not by this - License give permission to use their names for publicity for or to - assert or imply endorsement of any Modified Version. - - 5. COMBINING DOCUMENTS - - You may combine the Document with other documents released under - this License, under the terms defined in section 4 above for - modified versions, provided that you include in the combination - all of the Invariant Sections of all of the original documents, - unmodified, and list them all as Invariant Sections of your - combined work in its license notice, and that you preserve all - their Warranty Disclaimers. - - The combined work need only contain one copy of this License, and - multiple identical Invariant Sections may be replaced with a single - copy. If there are multiple Invariant Sections with the same name - but different contents, make the title of each such section unique - by adding at the end of it, in parentheses, the name of the - original author or publisher of that section if known, or else a - unique number. Make the same adjustment to the section titles in - the list of Invariant Sections in the license notice of the - combined work. - - In the combination, you must combine any sections Entitled - "History" in the various original documents, forming one section - Entitled "History"; likewise combine any sections Entitled - "Acknowledgements", and any sections Entitled "Dedications". You - must delete all sections Entitled "Endorsements." - - 6. COLLECTIONS OF DOCUMENTS - - You may make a collection consisting of the Document and other - documents released under this License, and replace the individual - copies of this License in the various documents with a single copy - that is included in the collection, provided that you follow the - rules of this License for verbatim copying of each of the - documents in all other respects. - - You may extract a single document from such a collection, and - distribute it individually under this License, provided you insert - a copy of this License into the extracted document, and follow - this License in all other respects regarding verbatim copying of - that document. - - 7. AGGREGATION WITH INDEPENDENT WORKS - - A compilation of the Document or its derivatives with other - separate and independent documents or works, in or on a volume of - a storage or distribution medium, is called an "aggregate" if the - copyright resulting from the compilation is not used to limit the - legal rights of the compilation's users beyond what the individual - works permit. When the Document is included in an aggregate, this - License does not apply to the other works in the aggregate which - are not themselves derivative works of the Document. - - If the Cover Text requirement of section 3 is applicable to these - copies of the Document, then if the Document is less than one half - of the entire aggregate, the Document's Cover Texts may be placed - on covers that bracket the Document within the aggregate, or the - electronic equivalent of covers if the Document is in electronic - form. Otherwise they must appear on printed covers that bracket - the whole aggregate. - - 8. TRANSLATION - - Translation is considered a kind of modification, so you may - distribute translations of the Document under the terms of section - 4. Replacing Invariant Sections with translations requires special - permission from their copyright holders, but you may include - translations of some or all Invariant Sections in addition to the - original versions of these Invariant Sections. You may include a - translation of this License, and all the license notices in the - Document, and any Warranty Disclaimers, provided that you also - include the original English version of this License and the - original versions of those notices and disclaimers. In case of a - disagreement between the translation and the original version of - this License or a notice or disclaimer, the original version will - prevail. - - If a section in the Document is Entitled "Acknowledgements", - "Dedications", or "History", the requirement (section 4) to - Preserve its Title (section 1) will typically require changing the - actual title. - - 9. TERMINATION - - You may not copy, modify, sublicense, or distribute the Document - except as expressly provided for under this License. Any other - attempt to copy, modify, sublicense or distribute the Document is - void, and will automatically terminate your rights under this - License. However, parties who have received copies, or rights, - from you under this License will not have their licenses - terminated so long as such parties remain in full compliance. - - 10. FUTURE REVISIONS OF THIS LICENSE - - The Free Software Foundation may publish new, revised versions of - the GNU Free Documentation License from time to time. Such new - versions will be similar in spirit to the present version, but may - differ in detail to address new problems or concerns. See - `http://www.gnu.org/copyleft/'. - - Each version of the License is given a distinguishing version - number. If the Document specifies that a particular numbered - version of this License "or any later version" applies to it, you - have the option of following the terms and conditions either of - that specified version or of any later version that has been - published (not as a draft) by the Free Software Foundation. If - the Document does not specify a version number of this License, - you may choose any version ever published (not as a draft) by the - Free Software Foundation. - -A.0.1 ADDENDUM: How to use this License for your documents ----------------------------------------------------------- - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and license -notices just after the title page: - - Copyright (C) YEAR YOUR NAME. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.2 - or any later version published by the Free Software Foundation; - with no Invariant Sections, no Front-Cover Texts, and no Back-Cover - Texts. A copy of the license is included in the section entitled ``GNU - Free Documentation License''. - - If you have Invariant Sections, Front-Cover Texts and Back-Cover -Texts, replace the "with...Texts." line with this: - - with the Invariant Sections being LIST THEIR TITLES, with - the Front-Cover Texts being LIST, and with the Back-Cover Texts - being LIST. - - If you have Invariant Sections without Cover Texts, or some other -combination of the three, merge those two alternatives to suit the -situation. - - If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of -free software license, such as the GNU Affero General Public License, to -permit their use in free software. - - -File: user-guide.info, Node: Index, Prev: GNU Free Documentation Licence, Up: Top - -Index -***** - - -* Menu: - -* alu (scheduler): Unify. (line 49) -* AppArmour: Troubleshooting. (line 96) -* arch: Getting GlusterFS. (line 6) -* booster: Booster. (line 6) -* commercial support: Introduction. (line 36) -* DNS round robin: Transport modules. (line 29) -* fcntl: POSIX Locks. (line 6) -* FDL, GNU Free Documentation License: GNU Free Documentation Licence. - (line 6) -* fixed-id (translator): Fixed ID. (line 6) -* GlusterFS client: Client. (line 6) -* GlusterFS mailing list: Introduction. (line 28) -* GlusterFS server: Server. (line 6) -* infiniband transport: Transport modules. (line 58) -* InfiniBand, installation: Pre requisites. (line 51) -* io-cache (translator): IO Cache. (line 6) -* io-threads (translator): IO Threads. (line 6) -* IRC channel, #gluster: Introduction. (line 31) -* libibverbs: Pre requisites. (line 51) -* namespace: Unify. (line 207) -* nufa (scheduler): Unify. (line 175) -* OpenSuSE: Troubleshooting. (line 96) -* posix-locks (translator): POSIX Locks. (line 6) -* random (scheduler): Unify. (line 159) -* read-ahead (translator): Read Ahead. (line 6) -* record locking: POSIX Locks. (line 6) -* Redhat Enterprise Linux: Troubleshooting. (line 78) -* Replicate: Replicate. (line 6) -* rot-13 (translator): ROT-13. (line 6) -* rr (scheduler): Unify. (line 138) -* scheduler (unify): Unify. (line 6) -* self heal (replicate): Replicate. (line 46) -* self heal (unify): Unify. (line 223) -* stripe (translator): Stripe. (line 6) -* trace (translator): Trace. (line 6) -* unify (translator): Unify. (line 6) -* unify invariants: Unify. (line 16) -* write-behind (translator): Write Behind. (line 6) -* Gluster, Inc.: Introduction. (line 36) - - - -Tag Table: -Node: Top704 -Node: Acknowledgements2304 -Node: Introduction3214 -Node: Installation and Invocation4649 -Node: Pre requisites4933 -Node: Getting GlusterFS7023 -Ref: Getting GlusterFS-Footnote-17809 -Node: Building7857 -Node: Running GlusterFS9559 -Node: Server9770 -Node: Client11358 -Node: A Tutorial Introduction13564 -Node: Concepts17101 -Node: Filesystems in Userspace17316 -Node: Translator18457 -Node: Volume specification file21160 -Node: Translators23632 -Node: Storage Translators24201 -Ref: Storage Translators-Footnote-125008 -Node: POSIX25142 -Node: BDB25765 -Node: Client and Server Translators26822 -Node: Transport modules27298 -Node: Client protocol31445 -Node: Server protocol32384 -Node: Clustering Translators33373 -Node: Unify34260 -Ref: Unify-Footnote-143859 -Node: Replicate43951 -Node: Stripe49006 -Node: Performance Translators50164 -Node: Read Ahead50438 -Node: Write Behind52170 -Node: IO Threads53579 -Node: IO Cache54367 -Node: Booster55691 -Node: Features Translators57105 -Node: POSIX Locks57333 -Node: Fixed ID58650 -Node: Miscellaneous Translators59136 -Node: ROT-1359334 -Node: Trace60013 -Node: Usage Scenarios61282 -Ref: Usage Scenarios-Footnote-167215 -Node: Troubleshooting67290 -Node: GNU Free Documentation Licence73638 -Node: Index96087 - -End Tag Table diff --git a/doc/user-guide/user-guide.pdf b/doc/user-guide/user-guide.pdf Binary files differdeleted file mode 100644 index ed7bd2a9907..00000000000 --- a/doc/user-guide/user-guide.pdf +++ /dev/null diff --git a/doc/user-guide/user-guide.texi b/doc/user-guide/user-guide.texi deleted file mode 100644 index b679dee024d..00000000000 --- a/doc/user-guide/user-guide.texi +++ /dev/null @@ -1,2246 +0,0 @@ -\input texinfo -@setfilename user-guide.info -@settitle GlusterFS 2.0 User Guide -@afourpaper - -@direntry -* GlusterFS: (user-guide). GlusterFS distributed filesystem user guide -@end direntry - -@copying -This is the user manual for GlusterFS 2.0. - -Copyright @copyright{} 2007-2010 @email{@b{Gluster}} , Inc. Permission is granted to -copy, distribute and/or modify this document under the terms of the -@acronym{GNU} Free Documentation License, Version 1.2 or any later -version published by the Free Software Foundation; with no Invariant -Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the -license is included in the chapter entitled ``@acronym{GNU} Free -Documentation License''. -@end copying - -@titlepage -@title GlusterFS 2.0 User Guide [DRAFT] -@subtitle January 15, 2008 -@author http://gluster.org/core-team.php -@author @email{@b{Gluster}} -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@c Info stuff -@ifnottex -@node Top -@top GlusterFS 2.0 User Guide - -@insertcopying -@menu -* Acknowledgements:: -* Introduction:: -* Installation and Invocation:: -* Concepts:: -* Translators:: -* Usage Scenarios:: -* Troubleshooting:: -* GNU Free Documentation Licence:: -* Index:: - -@detailmenu - --- The Detailed Node Listing --- - -Installation and Invocation - -* Pre requisites:: -* Getting GlusterFS:: -* Building:: -* Running GlusterFS:: -* A Tutorial Introduction:: - -Running GlusterFS - -* Server:: -* Client:: - -Concepts - -* Filesystems in Userspace:: -* Translator:: -* Volume specification file:: - -Translators - -* Storage Translators:: -* Client and Server Translators:: -* Clustering Translators:: -* Performance Translators:: -* Features Translators:: - -Storage Translators - -* POSIX:: - -Client and Server Translators - -* Transport modules:: -* Client protocol:: -* Server protocol:: - -Clustering Translators - -* Unify:: -* Replicate:: -* Stripe:: - -Performance Translators - -* Read Ahead:: -* Write Behind:: -* IO Threads:: -* IO Cache:: - -Features Translators - -* POSIX Locks:: -* Fixed ID:: - -Miscellaneous Translators - -* ROT-13:: -* Trace:: - -@end detailmenu -@end menu - -@end ifnottex -@c Info stuff end - -@contents - -@node Acknowledgements -@unnumbered Acknowledgements -GlusterFS continues to be a wonderful and enriching experience for all -of us involved. - -GlusterFS development would not have been possible at this pace if -not for our enthusiastic users. People from around the world have -helped us with bug reports, performance numbers, and feature suggestions. -A huge thanks to them all. - -Matthew Paine - for RPMs & general enthu - -Leonardo Rodrigues de Mello - for DEBs - -Julian Perez & Adam D'Auria - for multi-server tutorial - -Paul England - for HA spec - -Brent Nelson - for many bug reports - -Jacques Mattheij - for Europe mirror. - -Patrick Negri - for TCP non-blocking connect. -@flushright -http://gluster.org/core-team.php (@email{list-hacking@@gluster.com}) -@email{@b{Gluster}} -@end flushright - -@node Introduction -@chapter Introduction - -GlusterFS is a distributed filesystem. It works at the file level, -not block level. - -A network filesystem is one which allows us to access remote files. A -distributed filesystem is one that stores data on multiple machines -and makes them all appear to be a part of the same filesystem. - -Need for distributed filesystems - -@itemize @bullet -@item Scalability: A distributed filesystem allows us to store more data than what can be stored on a single machine. - -@item Redundancy: We might want to replicate crucial data on to several machines. - -@item Uniform access: One can mount a remote volume (for example your home directory) from any machine and access the same data. -@end itemize - -@section Contacting us -You can reach us through the mailing list @strong{gluster-devel} -(@email{gluster-devel@@nongnu.org}). -@cindex GlusterFS mailing list - -You can also find many of the developers on @acronym{IRC}, on the @code{#gluster} -channel on Freenode (@indicateurl{irc.freenode.net}). -@cindex IRC channel, #gluster - -The GlusterFS documentation wiki is also useful: @* -@indicateurl{http://gluster.org/docs/index.php/GlusterFS} - -For commercial support, you can contact @email{@b{Gluster}} at: -@cindex commercial support -@cindex Gluster, Inc. - -@display -3194 Winding Vista Common -Fremont, CA 94539 -USA. - -Phone: +1 (510) 354 6801 -Toll free: +1 (888) 813 6309 -Fax: +1 (510) 372 0604 -@end display - -You can also email us at @email{support@@gluster.com}. - -@node Installation and Invocation -@chapter Installation and Invocation - -@menu -* Pre requisites:: -* Getting GlusterFS:: -* Building:: -* Running GlusterFS:: -* A Tutorial Introduction:: -@end menu - -@node Pre requisites -@section Pre requisites - -Before installing GlusterFS make sure you have the -following components installed. - -@subsection @acronym{FUSE} -GlusterFS has now built-in support for the @acronym{FUSE} protocol. -You need a kernel with @acronym{FUSE} support to mount GlusterFS. -You do not need the @acronym{FUSE} package (library and utilities), -but be aware of the following issues: - -@itemize -@item If you want unprivileged users to be able to mount GlusterFS filesystems, -you need a recent version of the @command{fusermount} utility. You already have -it if you have @acronym{FUSE} version 2.7.0 or higher installed; if that's not -the case, one will be compiled along with GlusterFS if you pass -@command{--enable-fusermount} to the @command{configure} script. @item You -need to ensure @acronym{FUSE} support is configured properly on your system. In -details: -@itemize -@item If your kernel has @acronym{FUSE} as a loadable module, make sure it's -loaded. -@item Create @command{/dev/fuse} (major 10, minor 229) either by means of udev -rules or by hand. -@item Optionally, if you want runtime control over your @acronym{FUSE} mounts, -mount the fusectl auxiliary filesystem: - -@example -# mount -t fusectl none /sys/fs/fuse/connections -@end example -@end itemize - -The @acronym{FUSE} packages shipped by the various distributions usually take care -about these things, so the easiest way to get the above tasks handled is still -installing the @acronym{FUSE} package(s). -@end itemize - -To get the best performance from GlusterFS,it is recommended that you use -our patched version of the @acronym{FUSE} kernel module. See Patched FUSE for details. - -@subsection Patched FUSE - -The GlusterFS project maintains a patched version of @acronym{FUSE} meant to be used -with GlusterFS. The patches increase GlusterFS performance. It is recommended that -all users use the patched @acronym{FUSE}. - -The patched @acronym{FUSE} tarball can be downloaded from: - -@indicateurl{ftp://ftp.gluster.com/pub/gluster/glusterfs/fuse/} - -The specific changes made to @acronym{FUSE} are: - -@itemize -@item The communication channel size between @acronym{FUSE} kernel module and GlusterFS has been increased to 1MB, permitting large reads and writes to be sent in bigger chunks. - -@item The kernel's read-ahead boundry has been extended upto 1MB. - -@item Block size returned in the @command{stat()}/@command{fstat()} calls tuned to 1MB, to make cp and similar commands perform I/O using that block size. - -@item @command{flock()} locking support has been added (although some rework in GlusterFS is needed for perfect compliance). -@end itemize - -@subsection libibverbs (optional) -@cindex InfiniBand, installation -@cindex libibverbs -This is only needed if you want GlusterFS to use InfiniBand as the -interconnect mechanism between server and client. You can get it from: - -@indicateurl{http://www.openfabrics.org/downloads.htm}. - -@subsection Bison and Flex -These should be already installed on most Linux systems. If not, use your distribution's -normal software installation procedures to install them. Make sure you install the -relevant developer packages also. - -@node Getting GlusterFS -@section Getting GlusterFS -@cindex arch -There are many ways to get hold of GlusterFS. For a production deployment, -the recommended method is to download the latest release tarball. -Release tarballs are available at: @indicateurl{http://gluster.org/download.php}. - -If you want the bleeding edge development source, you can get them -from the Git -@footnote{@indicateurl{http://git-scm.com}} -repository. First you must install Git itself. Then -you can check out the source - -@example -$ git clone git://git.sv.gnu.org/gluster.git glusterfs -@end example - -@node Building -@section Building -You can skip this section if you're installing from @acronym{RPM}s -or @acronym{DEB}s. - -GlusterFS uses the Autotools mechanism to build. As such, the procedure -is straight-forward. First, change into the GlusterFS source directory. - -@example -$ cd glusterfs-<version> -@end example - -If you checked out the source from the Arch repository, you'll need -to run @command{./autogen.sh} first. Note that you'll need to have -Autoconf and Automake installed for this. - -Run @command{configure}. - -@example -$ ./configure -@end example - -The configure script accepts the following options: - -@cartouche -@table @code - -@item --disable-ibverbs -Disable the InfiniBand transport mechanism. - -@item --disable-fuse-client -Disable the @acronym{FUSE} client. - -@item --disable-server -Disable building of the GlusterFS server. - -@item --disable-bdb -Disable building of Berkeley DB based storage translator. - -@item --disable-mod_glusterfs -Disable building of Apache/lighttpd glusterfs plugins. - -@item --disable-epoll -Use poll instead of epoll. - -@item --disable-libglusterfsclient -Disable building of libglusterfsclient - -@item --enable-fusermount -Build fusermount - -@end table -@end cartouche - -Build and install GlusterFS. - -@example -# make install -@end example - -The binaries (@command{glusterfsd} and @command{glusterfs}) will be by -default installed in @command{/usr/local/sbin/}. Translator, -scheduler, and transport shared libraries will be installed in -@command{/usr/local/lib/glusterfs/<version>/}. Sample volume -specification files will be in @command{/usr/local/etc/glusterfs/}. -This document itself can be found in -@command{/usr/local/share/doc/glusterfs/}. If you passed the @command{--prefix} -argument to the configure script, then replace @command{/usr/local} in the preceding -paths with the prefix. - -@node Running GlusterFS -@section Running GlusterFS - -@menu -* Server:: -* Client:: -@end menu - -@node Server -@subsection Server -@cindex GlusterFS server - -The GlusterFS server is necessary to export storage volumes to remote clients -(See @ref{Server protocol} for more info). This section documents the invocation -of the GlusterFS server program and all the command-line options accepted by it. - -@cartouche -@table @code -Basic Options -@item -f, --volfile=<path> - Use the volume file as the volume specification. - -@item -s, --volfile-server=<hostname> - Server to get volume file from. This option overrides --volfile option. - -@item -l, --log-file=<path> - Specify the path for the log file. - -@item -L, --log-level=<level> - Set the log level for the server. Log level should be one of @acronym{DEBUG}, -@acronym{WARNING}, @acronym{ERROR}, @acronym{CRITICAL}, or @acronym{NONE}. - -Advanced Options -@item --debug - Run in debug mode. This option sets --no-daemon, --log-level to DEBUG and - --log-file to console. - -@item -N, --no-daemon - Run glusterfsd as a foreground process. - -@item -p, --pid-file=<path> - Path for the @acronym{PID} file. - -@item --volfile-id=<key> - 'key' of the volfile to be fetched from server. - -@item --volfile-server-port=<port-number> - Listening port number of volfile server. - -@item --volfile-server-transport=[socket|ib-verbs] - Transport type to get volfile from server. [default: @command{socket}] - -@item --xlator-options=<volume-name.option=value> - Add/override a translator option for a volume with specified value. - -Miscellaneous Options -@item -?, --help - Show this help text. - -@item --usage - Display a short usage message. - -@item -V, --version - Show version information. -@end table -@end cartouche - -@node Client -@subsection Client -@cindex GlusterFS client - -The GlusterFS client process is necessary to access remote storage volumes and -mount them locally using @acronym{FUSE}. This section documents the invocation of the -client process and all its command-line arguments. - -@example - # glusterfs [options] <mountpoint> -@end example - -The @command{mountpoint} is the directory where you want the GlusterFS -filesystem to appear. Example: - -@example - # glusterfs -f /usr/local/etc/glusterfs-client.vol /mnt -@end example - -The command-line options are detailed below. - -@tex -\vfill -@end tex -@page - -@cartouche -@table @code - -Basic Options -@item -f, --volfile=<path> - Use the volume file as the volume specification. - -@item -s, --volfile-server=<hostname> - Server to get volume file from. This option overrides --volfile option. - -@item -l, --log-file=<path> - Specify the path for the log file. - -@item -L, --log-level=<level> - Set the log level for the server. Log level should be one of @acronym{DEBUG}, -@acronym{WARNING}, @acronym{ERROR}, @acronym{CRITICAL}, or @acronym{NONE}. - -Advanced Options -@item --debug - Run in debug mode. This option sets --no-daemon, --log-level to DEBUG and - --log-file to console. - -@item -N, --no-daemon - Run @command{glusterfs} as a foreground process. - -@item -p, --pid-file=<path> - Path for the @acronym{PID} file. - -@item --volfile-id=<key> - 'key' of the volfile to be fetched from server. - -@item --volfile-server-port=<port-number> - Listening port number of volfile server. - -@item --volfile-server-transport=[socket|ib-verbs] - Transport type to get volfile from server. [default: @command{socket}] - -@item --xlator-options=<volume-name.option=value> - Add/override a translator option for a volume with specified value. - -@item --volume-name=<volume name> - Volume name in client spec to use. Defaults to the root volume. - -@acronym{FUSE} Options -@item --attribute-timeout=<n> - Attribute timeout for inodes in the kernel, in seconds. Defaults to 1 second. - -@item --disable-direct-io-mode - Disable direct @acronym{I/O} mode in @acronym{FUSE} kernel module. This is set - automatically if kernel supports big writes (>= 2.6.26). - -@item -e, --entry-timeout=<n> - Entry timeout for directory entries in the kernel, in seconds. - Defaults to 1 second. - -Missellaneous Options -@item -?, --help - Show this help information. - -@item -V, --version - Show version information. -@end table -@end cartouche - -@node A Tutorial Introduction -@section A Tutorial Introduction - -This section will show you how to quickly get GlusterFS up and running. We'll -configure GlusterFS as a simple network filesystem, with one server and one client. -In this mode of usage, GlusterFS can serve as a replacement for NFS. - -We'll make use of two machines; call them @emph{server} and -@emph{client} (If you don't want to setup two machines, just run -everything that follows on the same machine). In the examples that -follow, the shell prompts will use these names to clarify the machine -on which the command is being run. For example, a command that should -be run on the server will be shown with the prompt: - -@example -[root@@server]# -@end example - -Our goal is to make a directory on the @emph{server} (say, @command{/export}) -accessible to the @emph{client}. - -First of all, get GlusterFS installed on both the machines, as described in the -previous sections. Make sure you have the @acronym{FUSE} kernel module loaded. You -can ensure this by running: - -@example -[root@@server]# modprobe fuse -@end example - -Before we can run the GlusterFS client or server programs, we need to write -two files called @emph{volume specifications} (equivalently refered to as @emph{volfiles}). -The volfile describes the @emph{translator tree} on a node. The next chapter will -explain the concepts of `translator' and `volume specification' in detail. For now, -just assume that the volfile is like an NFS @command{/etc/export} file. - -On the server, create a text file somewhere (we'll assume the path -@command{/tmp/glusterfsd.vol}) with the following contents. - -@cartouche -@example -volume colon-o - type storage/posix - option directory /export -end-volume - -volume server - type protocol/server - subvolumes colon-o - option transport-type tcp - option auth.addr.colon-o.allow * -end-volume -@end example -@end cartouche - -A brief explanation of the file's contents. The first section defines a storage -volume, named ``colon-o'' (the volume names are arbitrary), which exports the -@command{/export} directory. The second section defines options for the translator -which will make the storage volume accessible remotely. It specifies @command{colon-o} as -a subvolume. This defines the @emph{translator tree}, about which more will be said -in the next chapter. The two options specify that the @acronym{TCP} protocol is to be -used (as opposed to InfiniBand, for example), and that access to the storage volume -is to be provided to clients with any @acronym{IP} address at all. If you wanted to -restrict access to this server to only your subnet for example, you'd specify -something like @command{192.168.1.*} in the second option line. - -On the client machine, create the following text file (again, we'll assume -the path to be @command{/tmp/glusterfs-client.vol}). Replace -@emph{server-ip-address} with the @acronym{IP} address of your server machine. If you -are doing all this on a single machine, use @command{127.0.0.1}. - -@cartouche -@example -volume client - type protocol/client - option transport-type tcp - option remote-host @emph{server-ip-address} - option remote-subvolume colon-o -end-volume -@end example -@end cartouche - -Now we need to start both the server and client programs. To start the server: - -@example -[root@@server]# glusterfsd -f /tmp/glusterfs-server.vol -@end example - -To start the client: - -@example -[root@@client]# glusterfs -f /tmp/glusterfs-client.vol /mnt/glusterfs -@end example - -You should now be able to see the files under the server's @command{/export} directory -in the @command{/mnt/glusterfs} directory on the client. That's it; GlusterFS is now -working as a network file system. - -@node Concepts -@chapter Concepts - -@menu -* Filesystems in Userspace:: -* Translator:: -* Volume specification file:: -@end menu - -@node Filesystems in Userspace -@section Filesystems in Userspace - -A filesystem is usually implemented in kernel space. Kernel space -development is much harder than userspace development. @acronym{FUSE} -is a kernel module/library that allows us to write a filesystem -completely in userspace. - -@acronym{FUSE} consists of a kernel module which interacts with the userspace -implementation using a device file @code{/dev/fuse}. When a process -makes a syscall on a @acronym{FUSE} filesystem, @acronym{VFS} hands the request to the -@acronym{FUSE} module, which writes the request to @code{/dev/fuse}. The -userspace implementation polls @code{/dev/fuse}, and when a request arrives, -processes it and writes the result back to @code{/dev/fuse}. The kernel then -reads from the device file and returns the result to the user process. - -In case of GlusterFS, the userspace program is the GlusterFS client. -The control flow is shown in the diagram below. The GlusterFS client -services the request by sending it to the server, which in turn -hands it to the local @acronym{POSIX} filesystem. - -@center @image{fuse,44pc,,,.pdf} -@center Fig 1. Control flow in GlusterFS - -@node Translator -@section Translator - -The @emph{translator} is the most important concept in GlusterFS. In -fact, GlusterFS is nothing but a collection of translators working -together, forming a translator @emph{tree}. - -The idea of a translator is perhaps best understood using an -analogy. Consider the @acronym{VFS} in the Linux kernel. The -@acronym{VFS} abstracts the various filesystem implementations (such -as @acronym{EXT3}, ReiserFS, @acronym{XFS}, etc.) supported by the -kernel. When an application calls the kernel to perform an operation -on a file, the kernel passes the request on to the appropriate -filesystem implementation. - -For example, let's say there are two partitions on a Linux machine: -@command{/}, which is an @acronym{EXT3} partition, and @command{/usr}, -which is a ReiserFS partition. Now if an application wants to open a -file called, say, @command{/etc/fstab}, then the kernel will -internally pass the request to the @acronym{EXT3} implementation. If -on the other hand, an application wants to read a file called -@command{/usr/src/linux/CREDITS}, then the kernel will call upon the -ReiserFS implementation to do the job. - -The ``filesystem implementation'' objects are analogous to GlusterFS -translators. A GlusterFS translator implements all the filesystem -operations. Whereas in @acronym{VFS} there is a two-level tree (with -the kernel at the root and all the filesystem implementation as its -children), in GlusterFS there exists a more elaborate tree structure. - -We can now define translators more precisely. A GlusterFS translator -is a shared object (@command{.so}) that implements every filesystem -call. GlusterFS translators can be arranged in an arbitrary tree -structure (subject to constraints imposed by the translators). When -GlusterFS receives a filesystem call, it passes it on to the -translator at the root of the translator tree. The root translator may -in turn pass it on to any or all of its children, and so on, until the -leaf nodes are reached. The result of a filesystem call is -communicated in the reverse fashion, from the leaf nodes up to the -root node, and then on to the application. - -So what might a translator tree look like? - -@tex -\vfill -@end tex -@page - -@center @image{xlator,44pc,,,.pdf} -@center Fig 2. A sample translator tree - -The diagram depicts three servers and one GlusterFS client. It is important -to note that conceptually, the translator tree spans machine boundaries. -Thus, the client machine in the diagram, @command{10.0.0.1}, can access -the aggregated storage of the filesystems on the server machines @command{10.0.0.2}, -@command{10.0.0.3}, and @command{10.0.0.4}. The translator diagram will make more -sense once you've read the next chapter and understood the functions of the -various translators. - -@node Volume specification file -@section Volume specification file -The volume specification file describes the translator tree for both the -server and client programs. - -A volume specification file is a sequence of volume definitions. -The syntax of a volume definition is explained below: - -@cartouche -@example -@strong{volume} @emph{volume-name} - @strong{type} @emph{translator-name} - @strong{option} @emph{option-name} @emph{option-value} - @dots{} - @strong{subvolumes} @emph{subvolume1} @emph{subvolume2} @dots{} -@strong{end-volume} -@end example - -@dots{} -@end cartouche - -@table @asis -@item @emph{volume-name} - An identifier for the volume. This is just a human-readable name, -and can contain any alphanumeric character. For instance, ``storage-1'', ``colon-o'', -or ``forty-two''. - -@item @emph{translator-name} - Name of one of the available translators. Example: @command{protocol/client}, -@command{cluster/unify}. - -@item @emph{option-name} - Name of a valid option for the translator. - -@item @emph{option-value} - Value for the option. Everything following the ``option'' keyword to the end of the -line is considered the value; it is up to the translator to parse it. - -@item @emph{subvolume1}, @emph{subvolume2}, @dots{} - Volume names of sub-volumes. The sub-volumes must already have been defined earlier -in the file. -@end table - -There are a few rules you must follow when writing a volume specification file: - -@itemize -@item Everything following a `@command{#}' is considered a comment and is ignored. Blank lines are also ignored. -@item All names and keywords are case-sensitive. -@item The order of options inside a volume definition does not matter. -@item An option value may not span multiple lines. -@item If an option is not specified, it will assume its default value. -@item A sub-volume must have already been defined before it can be referenced. This means you have to write the specification file ``bottom-up'', starting from the leaf nodes of the translator tree and moving up to the root. -@end itemize - -A simple example volume specification file is shown below: - -@cartouche -@example -# This is a comment line -volume client - type protocol/client - option transport-type tcp - option remote-host localhost # Also a comment - option remote-subvolume brick -# The subvolumes line may be absent -end-volume - -volume iot - type performance/io-threads - option thread-count 4 - subvolumes client -end-volume - -volume wb - type performance/write-behind - subvolumes iot -end-volume -@end example -@end cartouche - -@node Translators -@chapter Translators - -@menu -* Storage Translators:: -* Client and Server Translators:: -* Clustering Translators:: -* Performance Translators:: -* Features Translators:: -* Miscellaneous Translators:: -@end menu - -This chapter documents all the available GlusterFS translators in detail. -Each translator section will show its name (for example, @command{cluster/unify}), -briefly describe its purpose and workings, and list every option accepted by -that translator and their meaning. - -@node Storage Translators -@section Storage Translators - -The storage translators form the ``backend'' for GlusterFS. Currently, -the only available storage translator is the @acronym{POSIX} -translator, which stores files on a normal @acronym{POSIX} -filesystem. A pleasant consequence of this is that your data will -still be accessible if GlusterFS crashes or cannot be started. - -Other storage backends are planned for the future. One of the possibilities is an -Amazon S3 translator. Amazon S3 is an unlimited online storage service accessible -through a web services @acronym{API}. The S3 translator will allow you to access -the storage as a normal @acronym{POSIX} filesystem. -@footnote{Some more discussion about this can be found at: - -http://developer.amazonwebservices.com/connect/message.jspa?messageID=52873} - -@menu -* POSIX:: -* BDB:: -@end menu - -@node POSIX -@subsection POSIX -@example -type storage/posix -@end example - -The @command{posix} translator uses a normal @acronym{POSIX} -filesystem as its ``backend'' to actually store files and -directories. This can be any filesystem that supports extended -attributes (@acronym{EXT3}, ReiserFS, @acronym{XFS}, ...). Extended -attributes are used by some translators to store metadata, for -example, by the replicate and stripe translators. See -@ref{Replicate} and @ref{Stripe}, respectively for details. - -@cartouche -@table @code -@item directory <path> -The directory on the local filesystem which is to be used for storage. -@end table -@end cartouche - -@node BDB -@subsection BDB -@example -type storage/bdb -@end example - -The @command{BDB} translator uses a @acronym{Berkeley DB} database as its -``backend'' to actually store files as key-value pair in the database and -directories as regular @acronym{POSIX} directories. Note that @acronym{BDB} -does not provide extended attribute support for regular files. Do not use -@acronym{BDB} as storage translator while using any translator that demands -extended attributes on ``backend''. - -@cartouche -@table @code -@item directory <path> -The directory on the local filesystem which is to be used for storage. -@item mode [cache|persistent] (cache) -When @acronym{BDB} is run in @command{cache} mode, recovery of back-end is not completely -guaranteed. @command{persistent} guarantees that @acronym{BDB} can recover back-end from -@acronym{Berkeley DB} even if GlusterFS crashes. -@item errfile <path> -The path of the file to be used as @command{errfile} for @acronym{Berkeley DB} to report -detailed error messages, if any. Note that all the contents of this file will be written -by @acronym{Berkeley DB}, not GlusterFS. -@item logdir <path> - - -@end table -@end cartouche - -@node Client and Server Translators, Clustering Translators, Storage Translators, Translators -@section Client and Server Translators - -The client and server translator enable GlusterFS to export a -translator tree over the network or access a remote GlusterFS -server. These two translators implement GlusterFS's network protocol. - -@menu -* Transport modules:: -* Client protocol:: -* Server protocol:: -@end menu - -@node Transport modules -@subsection Transport modules -The client and server translators are capable of using any of the -pluggable transport modules. Currently available transport modules are -@command{tcp}, which uses a @acronym{TCP} connection between client -and server to communicate; @command{ib-sdp}, which uses a -@acronym{TCP} connection over InfiniBand, and @command{ibverbs}, which -uses high-speed InfiniBand connections. - -Each transport module comes in two different versions, one to be used on -the server side and the other on the client side. - -@subsubsection TCP - -The @acronym{TCP} transport module uses a @acronym{TCP/IP} connection between -the server and the client. - -@example - option transport-type tcp -@end example - -The @acronym{TCP} client module accepts the following options: - -@cartouche -@table @code -@item non-blocking-connect [no|off|on|yes] (on) -Whether to make the connection attempt asynchronous. -@item remote-port <n> (24007) -Server port to connect to. -@cindex DNS round robin -@item remote-host <hostname> * -Hostname or @acronym{IP} address of the server. If the host name resolves to -multiple IP addresses, all of them will be tried in a round-robin fashion. This -feature can be used to implement fail-over. -@end table -@end cartouche - -The @acronym{TCP} server module accepts the following options: - -@cartouche -@table @code -@item bind-address <address> (0.0.0.0) -The local interface on which the server should listen to requests. Default is to -listen on all interfaces. -@item listen-port <n> (24007) -The local port to listen on. -@end table -@end cartouche - -@subsubsection IB-SDP -@example - option transport-type ib-sdp -@end example - -kernel implements socket interface for ib hardware. SDP is over ib-verbs. -This module accepts the same options as @command{tcp} - -@subsubsection ibverbs - -@example - option transport-type tcp -@end example - -@cindex infiniband transport - -InfiniBand is a scalable switched fabric interconnect mechanism -primarily used in high-performance computing. InfiniBand can deliver -data throughput of the order of 10 Gbit/s, with latencies of 4-5 ms. - -The @command{ib-verbs} transport accesses the InfiniBand hardware through -the ``verbs'' @acronym{API}, which is the lowest level of software access possible -and which gives the highest performance. On InfiniBand hardware, it is always -best to use @command{ib-verbs}. Use @command{ib-sdp} only if you cannot get -@command{ib-verbs} working for some reason. - -The @command{ib-verbs} client module accepts the following options: - -@cartouche -@table @code -@item non-blocking-connect [no|off|on|yes] (on) -Whether to make the connection attempt asynchronous. -@item remote-port <n> (24007) -Server port to connect to. -@cindex DNS round robin -@item remote-host <hostname> * -Hostname or @acronym{IP} address of the server. If the host name resolves to -multiple IP addresses, all of them will be tried in a round-robin fashion. This -feature can be used to implement fail-over. -@end table -@end cartouche - -The @command{ib-verbs} server module accepts the following options: - -@cartouche -@table @code -@item bind-address <address> (0.0.0.0) -The local interface on which the server should listen to requests. Default is to -listen on all interfaces. -@item listen-port <n> (24007) -The local port to listen on. -@end table -@end cartouche - -The following options are common to both the client and server modules: - -If you are familiar with InfiniBand jargon, -the mode is used by GlusterFS is ``reliable connection-oriented channel transfer''. - -@cartouche -@table @code -@item ib-verbs-work-request-send-count <n> (64) -Length of the send queue in datagrams. [Reason to increase/decrease?] - -@item ib-verbs-work-request-recv-count <n> (64) -Length of the receive queue in datagrams. [Reason to increase/decrease?] - -@item ib-verbs-work-request-send-size <size> (128KB) -Size of each datagram that is sent. [Reason to increase/decrease?] - -@item ib-verbs-work-request-recv-size <size> (128KB) -Size of each datagram that is received. [Reason to increase/decrease?] - -@item ib-verbs-port <n> (1) -Port number for ib-verbs. - -@item ib-verbs-mtu [256|512|1024|2048|4096] (2048) -The Maximum Transmission Unit [Reason to increase/decrease?] - -@item ib-verbs-device-name <device-name> (first device in the list) -InfiniBand device to be used. -@end table -@end cartouche - -For maximum performance, you should ensure that the send/receive counts on both -the client and server are the same. - -ib-verbs is preferred over ib-sdp. - -@node Client protocol -@subsection Client -@example -type procotol/client -@end example - -The client translator enables the GlusterFS client to access a remote server's -translator tree. - -@cartouche -@table @code - -@item transport-type [tcp,ib-sdp,ib-verbs] (tcp) -The transport type to use. You should use the client versions of all the -transport modules (@command{tcp}, @command{ib-sdp}, -@command{ib-verbs}). -@item remote-subvolume <volume_name> * -The name of the volume on the remote host to attach to. Note that -this is @emph{not} the name of the @command{protocol/server} volume on the -server. It should be any volume under the server. -@item transport-timeout <n> (120- seconds) -Inactivity timeout. If a reply is expected and no activity takes place -on the connection within this time, the transport connection will be -broken, and a new connection will be attempted. -@end table -@end cartouche - -@node Server protocol -@subsection Server -@example -type protocol/server -@end example - -The server translator exports a translator tree and makes it accessible to -remote GlusterFS clients. - -@cartouche -@table @code -@item client-volume-filename <path> (<CONFDIR>/glusterfs-client.vol) -The volume specification file to use for the client. This is the file the -client will receive when it is invoked with the @command{--server} option -(@ref{Client}). - -@item transport-type [tcp,ib-verbs,ib-sdp] (tcp) -The transport to use. You should use the server versions of all the transport -modules (@command{tcp}, @command{ib-sdp}, @command{ib-verbs}). - -@item auth.addr.<volume name>.allow <IP address wildcard pattern> -IP addresses of the clients that are allowed to attach to the specified volume. -This can be a wildcard. For example, a wildcard of the form @command{192.168.*.*} -allows any host in the @command{192.168.x.x} subnet to connect to the server. - -@end table -@end cartouche - -@node Clustering Translators -@section Clustering Translators - -The clustering translators are the most important GlusterFS -translators, since it is these that make GlusterFS a cluster -filesystem. These translators together enable GlusterFS to access an -arbitrarily large amount of storage, and provide @acronym{RAID}-like -redundancy and distribution over the entire cluster. - -There are three clustering translators: @strong{unify}, @strong{replicate}, -and @strong{stripe}. The unify translator aggregates storage from -many server nodes. The replicate translator provides file replication. The stripe -translator allows a file to be spread across many server nodes. The following sections -look at each of these translators in detail. - -@menu -* Unify:: -* Replicate:: -* Stripe:: -@end menu - -@node Unify -@subsection Unify -@cindex unify (translator) -@cindex scheduler (unify) -@example -type cluster/unify -@end example - -The unify translator presents a `unified' view of all its sub-volumes. That is, -it makes the union of all its sub-volumes appear as a single volume. It is the -unify translator that gives GlusterFS the ability to access an arbitrarily -large amount of storage. - -For unify to work correctly, certain invariants need to be maintained across -the entire network. These are: - -@cindex unify invariants -@itemize -@item The directory structure of all the sub-volumes must be identical. -@item A particular file can exist on only one of the sub-volumes. Phrasing it in another way, a pathname such as @command{/home/calvin/homework.txt}) is unique across the entire cluster. -@end itemize - -@tex -\vfill -@end tex -@page - -@center @image{unify,44pc,,,.pdf} - -Looking at the second requirement, you might wonder how one can -accomplish storing redundant copies of a file, if no file can exist -multiple times. To answer, we must remember that these invariants are -from @emph{unify's perspective}. A translator such as replicate at a lower -level in the translator tree than unify may subvert this picture. - -The first invariant might seem quite tedious to ensure. We shall see -later that this is not so, since unify's @emph{self-heal} mechanism -takes care of maintaining it. - -The second invariant implies that unify needs some way to decide which file goes where. -Unify makes use of @emph{scheduler} modules for this purpose. - -When a file needs to be created, unify's scheduler decides upon the -sub-volume to be used to store the file. There are many schedulers -available, each using a different algorithm and suitable for different -purposes. - -The various schedulers are described in detail in the sections that follow. - -@subsubsection ALU -@cindex alu (scheduler) - -@example - option scheduler alu -@end example - -ALU stands for "Adaptive Least Usage". It is the most advanced -scheduler available in GlusterFS. It balances the load across volumes -taking several factors in account. It adapts itself to changing I/O -patterns according to its configuration. When properly configured, it -can eliminate the need for regular tuning of the filesystem to keep -volume load nicely balanced. - -The ALU scheduler is composed of multiple least-usage -sub-schedulers. Each sub-scheduler keeps track of a certain type of -load, for each of the sub-volumes, getting statistics from -the sub-volumes themselves. The sub-schedulers are these: - -@itemize -@item disk-usage: The used and free disk space on the volume. - -@item read-usage: The amount of reading done from this volume. - -@item write-usage: The amount of writing done to this volume. - -@item open-files-usage: The number of files currently open from this volume. - -@item disk-speed-usage: The speed at which the disks are spinning. This is a constant value and therefore not very useful. -@end itemize - -The ALU scheduler needs to know which of these sub-schedulers to use, -and in which order to evaluate them. This is done through the -@command{option alu.order} configuration directive. - -Each sub-scheduler needs to know two things: when to kick in (the -entry-threshold), and how long to stay in control (the -exit-threshold). For example: when unifying three disks of 100GB, -keeping an exact balance of disk-usage is not necesary. Instead, there -could be a 1GB margin, which can be used to nicely balance other -factors, such as read-usage. The disk-usage scheduler can be told to -kick in only when a certain threshold of discrepancy is passed, such -as 1GB. When it assumes control under this condition, it will write -all subsequent data to the least-used volume. If it is doing so, it is -unwise to stop right after the values are below the entry-threshold -again, since that would make it very likely that the situation will -occur again very soon. Such a situation would cause the ALU to spend -most of its time disk-usage scheduling, which is unfair to the other -sub-schedulers. The exit-threshold therefore defines the amount of -data that needs to be written to the least-used disk, before control -is relinquished again. - -In addition to the sub-schedulers, the ALU scheduler also has "limits" -options. These can stop the creation of new files on a volume once -values drop below a certain threshold. For example, setting -@command{option alu.limits.min-free-disk 5GB} will stop the scheduling -of files to volumes that have less than 5GB of free disk space, -leaving the files on that disk some room to grow. - -The actual values you assign to the thresholds for sub-schedulers and -limits depend on your situation. If you have fast-growing files, -you'll want to stop file-creation on a disk much earlier than when -hardly any of your files are growing. If you care less about -disk-usage balance than about read-usage balance, you'll want a bigger -disk-usage scheduler entry-threshold and a smaller read-usage -scheduler entry-threshold. - -For thresholds defining a size, values specifying "KB", "MB" and "GB" -are allowed. For example: @command{option alu.limits.min-free-disk 5GB}. - -@cartouche -@table @code -@item alu.order <order> * ("disk-usage:write-usage:read-usage:open-files-usage:disk-speed") -@item alu.disk-usage.entry-threshold <size> (1GB) -@item alu.disk-usage.exit-threshold <size> (512MB) -@item alu.write-usage.entry-threshold <%> (25) -@item alu.write-usage.exit-threshold <%> (5) -@item alu.read-usage.entry-threshold <%> (25) -@item alu.read-usage.exit-threshold <%> (5) -@item alu.open-files-usage.entry-threshold <n> (1000) -@item alu.open-files-usage.exit-threshold <n> (100) -@item alu.limits.min-free-disk <%> -@item alu.limits.max-open-files <n> -@end table -@end cartouche - -@subsubsection Round Robin (RR) -@cindex rr (scheduler) - -@example - option scheduler rr -@end example - -Round-Robin (RR) scheduler creates files in a round-robin -fashion. Each client will have its own round-robin loop. When your -files are mostly similar in size and I/O access pattern, this -scheduler is a good choice. RR scheduler checks for free disk space -on the server before scheduling, so you can know when to add -another server node. The default value of min-free-disk is 5% and is -checked on file creation calls, with atleast 10 seconds (by default) -elapsing between two checks. - -Options: -@cartouche -@table @code -@item rr.limits.min-free-disk <%> (5) -Minimum free disk space a node must have for RR to schedule a file to it. -@item rr.refresh-interval <t> (10 seconds) -Time between two successive free disk space checks. -@end table -@end cartouche - -@subsubsection Random -@cindex random (scheduler) - -@example - option scheduler random -@end example - -The random scheduler schedules file creation randomly among its child nodes. -Like the round-robin scheduler, it also checks for a minimum amount of free disk -space before scheduling a file to a node. - -@cartouche -@table @code -@item random.limits.min-free-disk <%> (5) -Minimum free disk space a node must have for random to schedule a file to it. -@item random.refresh-interval <t> (10 seconds) -Time between two successive free disk space checks. -@end table -@end cartouche - -@subsubsection NUFA -@cindex nufa (scheduler) - -@example - option scheduler nufa -@end example - -It is common in many GlusterFS computing environments for all deployed -machines to act as both servers and clients. For example, a -research lab may have 40 workstations each with its own storage. All -of these workstations might act as servers exporting a volume as well -as clients accessing the entire cluster's storage. In such a -situation, it makes sense to store locally created files on the local -workstation itself (assuming files are accessed most by the -workstation that created them). The Non-Uniform File Allocation (@acronym{NUFA}) -scheduler accomplishes that. - -@acronym{NUFA} gives the local system first priority for file creation -over other nodes. If the local volume does not have more free disk space -than a specified amount (5% by default) then @acronym{NUFA} schedules files -among the other child volumes in a round-robin fashion. - -@acronym{NUFA} is named after the similar strategy used for memory access, -@acronym{NUMA}@footnote{Non-Uniform Memory Access: -@indicateurl{http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access}}. - -@cartouche -@table @code -@item nufa.limits.min-free-disk <%> (5) -Minimum disk space that must be free (local or remote) for @acronym{NUFA} to schedule a -file to it. -@item nufa.refresh-interval <t> (10 seconds) -Time between two successive free disk space checks. -@item nufa.local-volume-name <volume> -The name of the volume corresponding to the local system. This volume must be -one of the children of the unify volume. This option is mandatory. -@end table -@end cartouche - -@cindex namespace -@subsubsection Namespace -Namespace volume needed because: - - persistent inode numbers. - - file exists even when node is down. - -namespace files are simply touched. on every lookup it is checked. - -@cartouche -@table @code -@item namespace <volume> * -Name of the namespace volume (which should be one of the unify volume's children). -@item self-heal [on|off] (on) -Enable/disable self-heal. Unless you know what you are doing, do not disable self-heal. -@end table -@end cartouche - -@cindex self heal (unify) -@subsubsection Self Heal - * When a 'lookup()/stat()' call is made on directory for the first -time, a self-heal call is made, which checks for the consistancy of -its child nodes. If an entry is present in storage node, but not in -namespace, that entry is created in namespace, and vica-versa. There -is an writedir() API introduced which is used for the same. It also -checks for permissions, and uid/gid consistencies. - - * This check is also done when an server goes down and comes up. - - * If one starts with an empty namespace export, but has data in -storage nodes, a 'find .>/dev/null' or 'ls -lR >/dev/null' should help -to build namespace in one shot. Even otherwise, namespace is built on -demand when a file is looked up for the first time. - -NOTE: There are some issues (Kernel 'Oops' msgs) seen with fuse-2.6.3, -when someone deletes namespace in backend, when glusterfs is -running. But with fuse-2.6.5, this issue is not there. - -@node Replicate -@subsection Replicate (formerly AFR) -@cindex Replicate -@example -type cluster/replicate -@end example - -Replicate provides @acronym{RAID}-1 like functionality for -GlusterFS. Replicate replicates files and directories across the -subvolumes. Hence if Replicate has four subvolumes, there will be -four copies of all files and directories. Replicate provides -high-availability, i.e., in case one of the subvolumes go down -(e. g. server crash, network disconnection) Replicate will still -service the requests using the redundant copies. - -Replicate also provides self-heal functionality, i.e., in case the -crashed servers come up, the outdated files and directories will be -updated with the latest versions. Replicate uses extended -attributes of the backend file system to track the versioning of files -and directories and provide the self-heal feature. - -@example -volume replicate-example - type cluster/replicate - subvolumes brick1 brick2 brick3 -end-volume -@end example - -This sample configuration will replicate all directories and files on -brick1, brick2 and brick3. - -All the read operations happen from the first alive child. If all the -three sub-volumes are up, reads will be done from brick1; if brick1 is -down read will be done from brick2. In case read() was being done on -brick1 and it goes down, replicate transparently falls back to -brick2. - -The next release of GlusterFS will add the following features: -@itemize -@item Ability to specify the sub-volume from which read operations are to be done (this will help users who have one of the sub-volumes as a local storage volume). -@item Allow scheduling of read operations amongst the sub-volumes in a round-robin fashion. -@end itemize - -The order of the subvolumes list should be same across all the 'replicate's as -they will be used for locking purposes. - -@cindex self heal (replicate) -@subsubsection Self Heal -Replicate has self-heal feature, which updates the outdated file and -directory copies by the most recent versions. For example consider the -following config: - -@example -volume replicate-example - type cluster/replicate - subvolumes brick1 brick2 -end-volume -@end example - -@subsubsection File self-heal - -Now if we create a file foo.txt on replicate-example, the file will be created -on brick1 and brick2. The file will have two extended attributes associated -with it in the backend filesystem. One is trusted.afr.createtime and the -other is trusted.afr.version. The trusted.afr.createtime xattr has the -create time (in terms of seconds since epoch) and trusted.afr.version -is a number that is incremented each time a file is modified. This increment -happens during close (incase any write was done before close). - -If brick1 goes down, we edit foo.txt the version gets incremented. Now -the brick1 comes back up, when we open() on foo.txt replicate will check if -their versions are same. If they are not same, the outdated copy is -replaced by the latest copy and its version is updated. After the sync -the open() proceeds in the usual manner and the application calling open() -can continue on its access to the file. - -If brick1 goes down, we delete foo.txt and create a file with the same -name again i.e foo.txt. Now brick1 comes back up, clearly there is a -chance that the version on brick1 being more than the version on brick2, -this is where createtime extended attribute helps in deciding which -the outdated copy is. Hence we need to consider both createtime and -version to decide on the latest copy. - -The version attribute is incremented during the close() call. Version -will not be incremented in case there was no write() done. In case the -fd that the close() gets was got by create() call, we also create -the createtime extended attribute. - -@subsubsection Directory self-heal - -Suppose brick1 goes down, we delete foo.txt, brick1 comes back up, now -we should not create foo.txt on brick2 but we should delete foo.txt -on brick1. We handle this situation by having the createtime and version -attribute on the directory similar to the file. when lookup() is done -on the directory, we compare the createtime/version attributes of the -copies and see which files needs to be deleted and delete those files -and update the extended attributes of the outdated directory copy. -Each time a directory is modified (a file or a subdirectory is created -or deleted inside the directory) and one of the subvols is down, we -increment the directory's version. - -lookup() is a call initiated by the kernel on a file or directory -just before any access to that file or directory. In glusterfs, by -default, lookup() will not be called in case it was called in the -past one second on that particular file or directory. - -The extended attributes can be seen in the backend filesystem using -the @command{getfattr} command. (@command{getfattr -n trusted.afr.version <file>}) - -@cartouche -@table @code -@item debug [on|off] (off) -@item self-heal [on|off] (on) -@item replicate <pattern> (*:1) -@item lock-node <child_volume> (first child is used by default) -@end table -@end cartouche - -@node Stripe -@subsection Stripe -@cindex stripe (translator) -@example -type cluster/stripe -@end example - -The stripe translator distributes the contents of a file over its -sub-volumes. It does this by creating a file equal in size to the -total size of the file on each of its sub-volumes. It then writes only -a part of the file to each sub-volume, leaving the rest of it empty. -These empty regions are called `holes' in Unix terminology. The holes -do not consume any disk space. - -The diagram below makes this clear. - -@center @image{stripe,44pc,,,.pdf} - -You can configure stripe so that only filenames matching a pattern -are striped. You can also configure the size of the data to be stored -on each sub-volume. - -@cartouche -@table @code -@item block-size <pattern>:<size> (*:0 no striping) -Distribute files matching @command{<pattern>} over the sub-volumes, -storing at least @command{<size>} on each sub-volume. For example, - -@example - option block-size *.mpg:1M -@end example - -distributes all files ending in @command{.mpg}, storing at least 1 MB on -each sub-volume. - -Any number of @command{block-size} option lines may be present, specifying -different sizes for different file name patterns. -@end table -@end cartouche - -@node Performance Translators -@section Performance Translators - -@menu -* Read Ahead:: -* Write Behind:: -* IO Threads:: -* IO Cache:: -* Booster:: -@end menu - -@node Read Ahead -@subsection Read Ahead -@cindex read-ahead (translator) -@example -type performance/read-ahead -@end example - -The read-ahead translator pre-fetches data in advance on every read. -This benefits applications that mostly process files in sequential order, -since the next block of data will already be available by the time the -application is done with the current one. - -Additionally, the read-ahead translator also behaves as a read-aggregator. -Many small read operations are combined and issued as fewer, larger read -requests to the server. - -Read-ahead deals in ``pages'' as the unit of data fetched. The page size -is configurable, as is the ``page count'', which is the number of pages -that are pre-fetched. - -Read-ahead is best used with InfiniBand (using the ib-verbs transport). -On FastEthernet and Gigabit Ethernet networks, -GlusterFS can achieve the link-maximum throughput even without -read-ahead, making it quite superflous. - -Note that read-ahead only happens if the reads are perfectly -sequential. If your application accesses data in a random fashion, -using read-ahead might actually lead to a performance loss, since -read-ahead will pointlessly fetch pages which won't be used by the -application. - -@cartouche -Options: -@table @code -@item page-size <n> (256KB) -The unit of data that is pre-fetched. -@item page-count <n> (2) -The number of pages that are pre-fetched. -@item force-atime-update [on|off|yes|no] (off|no) -Whether to force an access time (atime) update on the file on every read. Without -this, the atime will be slightly imprecise, as it will reflect the time when -the read-ahead translator read the data, not when the application actually read it. -@end table -@end cartouche - -@node Write Behind -@subsection Write Behind -@cindex write-behind (translator) -@example -type performance/write-behind -@end example - -The write-behind translator improves the latency of a write operation. -It does this by relegating the write operation to the background and -returning to the application even as the write is in progress. Using the -write-behind translator, successive write requests can be pipelined. -This mode of write-behind operation is best used on the client side, to -enable decreased write latency for the application. - -The write-behind translator can also aggregate write requests. If the -@command{aggregate-size} option is specified, then successive writes upto that -size are accumulated and written in a single operation. This mode of operation -is best used on the server side, as this will decrease the disk's head movement -when multiple files are being written to in parallel. - -The @command{aggregate-size} option has a default value of 128KB. Although -this works well for most users, you should always experiment with different values -to determine the one that will deliver maximum performance. This is because the -performance of write-behind depends on your interconnect, size of RAM, and the -work load. - -@cartouche -@table @code -@item aggregate-size <n> (128KB) -Amount of data to accumulate before doing a write -@item flush-behind [on|yes|off|no] (off|no) - -@end table -@end cartouche - -@node IO Threads -@subsection IO Threads -@cindex io-threads (translator) -@example -type performance/io-threads -@end example - -The IO threads translator is intended to increase the responsiveness -of the server to metadata operations by doing file I/O (read, write) -in a background thread. Since the GlusterFS server is -single-threaded, using the IO threads translator can significantly -improve performance. This translator is best used on the server side, -loaded just below the server protocol translator. - -IO threads operates by handing out read and write requests to a separate thread. -The total number of threads in existence at a time is constant, and configurable. - -@cartouche -@table @code -@item thread-count <n> (1) -Number of threads to use. -@end table -@end cartouche - -@node IO Cache -@subsection IO Cache -@cindex io-cache (translator) -@example -type performance/io-cache -@end example - -The IO cache translator caches data that has been read. This is useful -if many applications read the same data multiple times, and if reads -are much more frequent than writes (for example, IO caching may be -useful in a web hosting environment, where most clients will simply -read some files and only a few will write to them). - -The IO cache translator reads data from its child in @command{page-size} chunks. -It caches data upto @command{cache-size} bytes. The cache is maintained as -a prioritized least-recently-used (@acronym{LRU}) list, with priorities determined -by user-specified patterns to match filenames. - -When the IO cache translator detects a write operation, the -cache for that file is flushed. - -The IO cache translator periodically verifies the consistency of -cached data, using the modification times on the files. The verification timeout -is configurable. - -@cartouche -@table @code -@item page-size <n> (128KB) -Size of a page. -@item cache-size (n) (32MB) -Total amount of data to be cached. -@item force-revalidate-timeout <n> (1) -Timeout to force a cache consistency verification, in seconds. -@item priority <pattern> (*:0) -Filename patterns listed in order of priority. -@end table -@end cartouche - -@node Booster -@subsection Booster -@cindex booster -@example - type performance/booster -@end example - -The booster translator gives applications a faster path to communicate -read and write requests to GlusterFS. Normally, all requests to GlusterFS from -applications go through FUSE, as indicated in @ref{Filesystems in Userspace}. -Using the booster translator in conjunction with the GlusterFS booster shared -library, an application can bypass the FUSE path and send read/write requests -directly to the GlusterFS client process. - -The booster mechanism consists of two parts: the booster translator, -and the booster shared library. The booster translator is meant to be -loaded on the client side, usually at the root of the translator tree. -The booster shared library should be @command{LD_PRELOAD}ed with the -application. - -The booster translator when loaded opens a Unix domain socket and -listens for read/write requests on it. The booster shared library -intercepts read and write system calls and sends the requests to the -GlusterFS process directly using the Unix domain socket, bypassing FUSE. -This leads to superior performance. - -Once you've loaded the booster translator in your volume specification file, you -can start your application as: - -@example - $ LD_PRELOAD=/usr/local/bin/glusterfs-booster.so your_app -@end example - -The booster translator accepts no options. - -@node Features Translators -@section Features Translators - -@menu -* POSIX Locks:: -* Fixed ID:: -@end menu - -@node POSIX Locks -@subsection POSIX Locks -@cindex record locking -@cindex fcntl -@cindex posix-locks (translator) -@example -type features/posix-locks -@end example - -This translator provides storage independent POSIX record locking -support (@command{fcntl} locking). Typically you'll want to load this on the -server side, just above the @acronym{POSIX} storage translator. Using this -translator you can get both advisory locking and mandatory locking -support. It also handles @command{flock()} locks properly. - -Caveat: Consider a file that does not have its mandatory locking bits -(+setgid, -group execution) turned on. Assume that this file is now -opened by a process on a client that has the write-behind xlator -loaded. The write-behind xlator does not cache anything for files -which have mandatory locking enabled, to avoid incoherence. Let's say -that mandatory locking is now enabled on this file through another -client. The former client will not know about this change, and -write-behind may erroneously report a write as being successful when -in fact it would fail due to the region it is writing to being locked. - -There seems to be no easy way to fix this. To work around this -problem, it is recommended that you never enable the mandatory bits on -a file while it is open. - -@cartouche -@table @code -@item mandatory [on|off] (on) -Turns mandatory locking on. -@end table -@end cartouche - -@node Fixed ID -@subsection Fixed ID -@cindex fixed-id (translator) -@example -type features/fixed-id -@end example - -The fixed ID translator makes all filesystem requests from the client -to appear to be coming from a fixed, specified -@acronym{UID}/@acronym{GID}, regardless of which user actually -initiated the request. - -@cartouche -@table @code -@item fixed-uid <n> [if not set, not used] -The @acronym{UID} to send to the server -@item fixed-gid <n> [if not set, not used] -The @acronym{GID} to send to the server -@end table -@end cartouche - -@node Miscellaneous Translators -@section Miscellaneous Translators - -@menu -* ROT-13:: -* Trace:: -@end menu - -@node ROT-13 -@subsection ROT-13 -@cindex rot-13 (translator) -@example -type encryption/rot-13 -@end example - -@acronym{ROT-13} is a toy translator that can ``encrypt'' and ``decrypt'' file -contents using the @acronym{ROT-13} algorithm. @acronym{ROT-13} is a trivial -algorithm that rotates each alphabet by thirteen places. Thus, 'A' becomes 'N', -'B' becomes 'O', and 'Z' becomes 'M'. - -It goes without saying that you shouldn't use this translator if you need -@emph{real} encryption (a future release of GlusterFS will have real encryption -translators). - -@cartouche -@table @code -@item encrypt-write [on|off] (on) -Whether to encrypt on write -@item decrypt-read [on|off] (on) -Whether to decrypt on read -@end table -@end cartouche - -@node Trace -@subsection Trace -@cindex trace (translator) -@example -type debug/trace -@end example - -The trace translator is intended for debugging purposes. When loaded, it -logs all the system calls received by the server or client (wherever -trace is loaded), their arguments, and the results. You must use a GlusterFS log -level of DEBUG (See @ref{Running GlusterFS}) for trace to work. - -Sample trace output (lines have been wrapped for readability): -@cartouche -@example -2007-10-30 00:08:58 D [trace.c:1579:trace_opendir] trace: callid: 68 -(*this=0x8059e40, loc=0x8091984 @{path=/iozone3_283, inode=0x8091f00@}, - fd=0x8091d50) - -2007-10-30 00:08:58 D [trace.c:630:trace_opendir_cbk] trace: -(*this=0x8059e40, op_ret=4, op_errno=1, fd=0x8091d50) - -2007-10-30 00:08:58 D [trace.c:1602:trace_readdir] trace: callid: 69 -(*this=0x8059e40, size=4096, offset=0 fd=0x8091d50) - -2007-10-30 00:08:58 D [trace.c:215:trace_readdir_cbk] trace: -(*this=0x8059e40, op_ret=0, op_errno=0, count=4) - -2007-10-30 00:08:58 D [trace.c:1624:trace_closedir] trace: callid: 71 -(*this=0x8059e40, *fd=0x8091d50) - -2007-10-30 00:08:58 D [trace.c:809:trace_closedir_cbk] trace: -(*this=0x8059e40, op_ret=0, op_errno=1) -@end example -@end cartouche - -@node Usage Scenarios -@chapter Usage Scenarios - -@section Advanced Striping - -This section is based on the Advanced Striping tutorial written by -Anand Avati on the GlusterFS wiki -@footnote{http://gluster.org/docs/index.php/Mixing_Striped_and_Regular_Files}. - -@subsection Mixed Storage Requirements - -There are two ways of scheduling the I/O. One at file level (using -unify translator) and other at block level (using stripe -translator). Striped I/O is good for files that are potentially large -and require high parallel throughput (for example, a single file of -400GB being accessed by 100s and 1000s of systems simultaneously and -randomly). For most of the cases, file level scheduling works best. - -In the real world, it is desirable to mix file level and block level -scheduling on a single storage volume. Alternatively users can choose -to have two separate volumes and hence two mount points, but the -applications may demand a single storage system to host both. - -This document explains how to mix file level scheduling with stripe. - -@subsection Configuration Brief - -This setup demonstrates how users can configure unify translator with -appropriate I/O scheduler for file level scheduling and strip for only -matching patterns. This way, GlusterFS chooses appropriate I/O profile -and knows how to efficiently handle both the types of data. - -A simple technique to achieve this effect is to create a stripe set of -unify and stripe blocks, where unify is the first sub-volume. Files -that do not match the stripe policy passed on to first unify -sub-volume and inturn scheduled arcoss the cluster using its file -level I/O scheduler. - -@image{advanced-stripe,44pc,,,.pdf} - -@subsection Preparing GlusterFS Envoronment - -Create the directories /export/namespace, /export/unify and -/export/stripe on all the storage bricks. - - Place the following server and client volume spec file under -/etc/glusterfs (or appropriate installed path) and replace the IP -addresses / access control fields to match your environment. - -@cartouche -@example - ## file: /etc/glusterfs/glusterfsd.vol - volume posix-unify - type storage/posix - option directory /export/for-unify - end-volume - - volume posix-stripe - type storage/posix - option directory /export/for-stripe - end-volume - - volume posix-namespace - type storage/posix - option directory /export/for-namespace - end-volume - - volume server - type protocol/server - option transport-type tcp - option auth.addr.posix-unify.allow 192.168.1.* - option auth.addr.posix-stripe.allow 192.168.1.* - option auth.addr.posix-namespace.allow 192.168.1.* - subvolumes posix-unify posix-stripe posix-namespace - end-volume -@end example -@end cartouche - -@cartouche -@example - ## file: /etc/glusterfs/glusterfs.vol - volume client-namespace - type protocol/client - option transport-type tcp - option remote-host 192.168.1.1 - option remote-subvolume posix-namespace - end-volume - - volume client-unify-1 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.1 - option remote-subvolume posix-unify - end-volume - - volume client-unify-2 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.2 - option remote-subvolume posix-unify - end-volume - - volume client-unify-3 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.3 - option remote-subvolume posix-unify - end-volume - - volume client-unify-4 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.4 - option remote-subvolume posix-unify - end-volume - - volume client-stripe-1 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.1 - option remote-subvolume posix-stripe - end-volume - - volume client-stripe-2 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.2 - option remote-subvolume posix-stripe - end-volume - - volume client-stripe-3 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.3 - option remote-subvolume posix-stripe - end-volume - - volume client-stripe-4 - type protocol/client - option transport-type tcp - option remote-host 192.168.1.4 - option remote-subvolume posix-stripe - end-volume - - volume unify - type cluster/unify - option scheduler rr - subvolumes cluster-unify-1 cluster-unify-2 cluster-unify-3 cluster-unify-4 - end-volume - - volume stripe - type cluster/stripe - option block-size *.img:2MB # All files ending with .img are striped with 2MB stripe block size. - subvolumes unify cluster-stripe-1 cluster-stripe-2 cluster-stripe-3 cluster-stripe-4 - end-volume -@end example -@end cartouche - - -Bring up the Storage - -Starting GlusterFS Server: If you have installed through binary -package, you can start the service through init.d startup script. If -not: - -@example -[root@@server]# glusterfsd -@end example - -Mounting GlusterFS Volumes: - -@example -[root@@client]# glusterfs -s [BRICK-IP-ADDRESS] /mnt/cluster -@end example - -Improving upon this Setup - -Infiniband Verbs RDMA transport is much faster than TCP/IP GigE -transport. - -Use of performance translators such as read-ahead, write-behind, -io-cache, io-threads, booster is recommended. - -Replace round-robin (rr) scheduler with ALU to handle more dynamic -storage environments. - -@node Troubleshooting -@chapter Troubleshooting - -This chapter is a general troubleshooting guide to GlusterFS. It lists -common GlusterFS server and client error messages, debugging hints, and -concludes with the suggested procedure to report bugs in GlusterFS. - -@section GlusterFS error messages - -@subsection Server errors - -@example -glusterfsd: FATAL: could not open specfile: -'/etc/glusterfs/glusterfsd.vol' -@end example - -The GlusterFS server expects the volume specification file to be -at @command{/etc/glusterfs/glusterfsd.vol}. The example -specification file will be installed as -@command{/etc/glusterfs/glusterfsd.vol.sample}. You need to edit -it and rename it, or provide a different specification file using -the @command{--spec-file} command line option (See @ref{Server}). - -@vskip 4ex - -@example -gf_log_init: failed to open logfile "/usr/var/log/glusterfs/glusterfsd.log" - (Permission denied) -@end example - -You don't have permission to create files in the -@command{/usr/var/log/glusterfs} directory. Make sure you are running -GlusterFS as root. Alternatively, specify a different path for the log -file using the @command{--log-file} option (See @ref{Server}). - -@subsection Client errors - -@example -fusermount: failed to access mountpoint /mnt: - Transport endpoint is not connected -@end example - -A previous failed (or hung) mount of GlusterFS is preventing it from being -mounted again in the same location. The fix is to do: - -@example -# umount /mnt -@end example - -and try mounting again. - -@vskip 4ex - -@strong{``Transport endpoint is not connected''.} - -If you get this error when you try a command such as @command{ls} or @command{cat}, -it means the GlusterFS mount did not succeed. Try running GlusterFS in @command{DEBUG} -logging level and study the log messages to discover the cause. - -@vskip 4ex - -@strong{``Connect to server failed'', ``SERVER-ADDRESS: Connection refused''.} - -GluserFS Server is not running or dead. Check your network -connections and firewall settings. To check if the server is reachable, -try: - -@example -telnet IP-ADDRESS 24007 -@end example - -If the server is accessible, your `telnet' command should connect and -block. If not you will see an error message such as @command{telnet: Unable to -connect to remote host: Connection refused}. 24007 is the default -GlusterFS port. If you have changed it, then use the corresponding -port instead. - -@vskip 4ex - -@example -gf_log_init: failed to open logfile "/usr/var/log/glusterfs/glusterfs.log" - (Permission denied) -@end example - -You don't have permission to create files in the -@command{/usr/var/log/glusterfs} directory. Make sure you are running -GlusterFS as root. Alternatively, specify a different path for the log -file using the @command{--log-file} option (See @ref{Client}). - -@section FUSE error messages -@command{modprobe fuse} fails with: ``Unknown symbol in module, or unknown parameter''. -@cindex Redhat Enterprise Linux - -If you are using fuse-2.6.x on Redhat Enterprise Linux Work Station 4 -and Advanced Server 4 with 2.6.9-42.ELlargesmp, 2.6.9-42.ELsmp, -2.6.9-42.EL kernels and get this error while loading @acronym{FUSE} kernel -module, you need to apply the following patch. - -For fuse-2.6.2: - -@indicateurl{http://ftp.gluster.com/pub/gluster/glusterfs/fuse/fuse-2.6.2-rhel-build.patch} - -For fuse-2.6.3: - -@indicateurl{http://ftp.gluster.com/pub/gluster/glusterfs/fuse/fuse-2.6.3-rhel-build.patch} - -@section AppArmour and GlusterFS -@cindex AppArmour -@cindex OpenSuSE -Under OpenSuSE GNU/Linux, the AppArmour security feature does not -allow GlusterFS to create temporary files or network socket -connections even while running as root. You will see error messages -like `Unable to open log file: Operation not permitted' or `Connection -refused'. Disabling AppArmour using YaST or properly configuring -AppArmour to recognize @command{glusterfsd} or @command{glusterfs}/@command{fusermount} -should solve the problem. - -@section Reporting a bug - -If you encounter a bug in GlusterFS, please follow the below -guidelines when you report it to the mailing list. Be sure to report -it! User feedback is crucial to the health of the project and we value -it highly. - -@subsection General instructions - -When running GlusterFS in a non-production environment, be sure to -build it with the following command: - -@example - $ make CFLAGS='-g -O0 -DDEBUG' -@end example - -This includes debugging information which will be helpful in getting -backtraces (see below) and also disable optimization. Enabling -optimization can result in incorrect line numbers being reported to -gdb. - -@subsection Volume specification files - -Attach all relevant server and client spec files you were using when -you encountered the bug. Also tell us details of your setup, i.e., how -many clients and how many servers. - -@subsection Log files - -Set the loglevel of your client and server programs to @acronym{DEBUG} (by -passing the -L @acronym{DEBUG} option) and attach the log files with your bug -report. Obviously, if only the client is failing (for example), you -only need to send us the client log file. - -@subsection Backtrace - -If GlusterFS has encountered a segmentation fault or has crashed for -some other reason, include the backtrace with the bug report. You can -get the backtrace using the following procedure. - -Run the GlusterFS client or server inside gdb. - -@example - $ gdb ./glusterfs - (gdb) set args -f client.spec -N -l/path/to/log/file -LDEBUG /mnt/point - (gdb) run -@end example - -Now when the process segfaults, you can get the backtrace by typing: - -@example - (gdb) bt -@end example - -If the GlusterFS process has crashed and dumped a core file (you can -find this in / if running as a daemon and in the current directory -otherwise), you can do: - -@example - $ gdb /path/to/glusterfs /path/to/core.<pid> -@end example - -and then get the backtrace. - -If the GlusterFS server or client seems to be hung, then you can get -the backtrace by attaching gdb to the process. First get the @command{PID} of -the process (using ps), and then do: - -@example - $ gdb ./glusterfs <pid> -@end example - -Press Ctrl-C to interrupt the process and then generate the backtrace. - -@subsection Reproducing the bug - -If the bug is reproducible, please include the steps necessary to do -so. If the bug is not reproducible, send us the bug report anyway. - -@subsection Other information - -If you think it is relevant, send us also the version of @acronym{FUSE} you're -using, the kernel version, platform. - -@node GNU Free Documentation Licence -@appendix GNU Free Documentation Licence -@include fdl.texi - -@node Index -@unnumbered Index -@printindex cp - -@bye diff --git a/doc/user-guide/xlator.odg b/doc/user-guide/xlator.odg Binary files differdeleted file mode 100644 index 179a65f6e26..00000000000 --- a/doc/user-guide/xlator.odg +++ /dev/null diff --git a/doc/user-guide/xlator.pdf b/doc/user-guide/xlator.pdf Binary files differdeleted file mode 100644 index a07e14d67d2..00000000000 --- a/doc/user-guide/xlator.pdf +++ /dev/null |
