diff options
-rw-r--r-- | libglusterfs/src/glusterfs.h | 4 | ||||
-rwxr-xr-x | tests/bugs/bug-990028.t | 156 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-quota.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 51 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 162 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix-handle.h | 96 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 87 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 759 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.h | 11 |
9 files changed, 1156 insertions, 171 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index d8c7060f7ef..525d6909a59 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -101,10 +101,14 @@ #define GF_XATTR_LINKINFO_KEY "trusted.distribute.linkinfo" #define GFID_XATTR_KEY "trusted.gfid" +#define PGFID_XATTR_KEY_PREFIX "trusted.pgfid." #define VIRTUAL_GFID_XATTR_KEY_STR "glusterfs.gfid.string" #define VIRTUAL_GFID_XATTR_KEY "glusterfs.gfid" #define UUID_CANONICAL_FORM_LEN 36 +#define GET_ANCESTRY_PATH_KEY "glusterfs.ancestry.path" +#define GET_ANCESTRY_DENTRY_KEY "glusterfs.ancestry.dentry" + #define GLUSTERFS_INTERNAL_FOP_KEY "glusterfs-internal-fop" #define ZR_FILE_CONTENT_STR "glusterfs.file." diff --git a/tests/bugs/bug-990028.t b/tests/bugs/bug-990028.t new file mode 100755 index 00000000000..ece7235cd96 --- /dev/null +++ b/tests/bugs/bug-990028.t @@ -0,0 +1,156 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../fileio.rc + +cleanup; + +TESTS_EXPECTED_IN_LOOP=153 + +function __init() +{ + TEST glusterd + TEST pidof glusterd + TEST $CLI volume info; + + TEST $CLI volume create $V0 $H0:$B0/brick + + EXPECT 'Created' volinfo_field $V0 'Status'; + + TEST $CLI volume start $V0 + + TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0 + + TEST $CLI volume quota $V0 enable + sleep 15 +} + +#CASE-1 +#checking pgfid under same directory +function links_in_same_directory() +{ + # create a file file1 + TEST touch $M0/file1 + + # create 50 hardlinks for file1 + for i in `seq 2 50`; do + TEST_IN_LOOP ln $M0/file1 $M0/file$i + done + + # store the pgfid of file1 in PGFID_FILE1 [should be 50 now (0x000000032)] + PGFID_FILE1=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/file1 2>&1 | grep "trusted.pgfid" | gawk -F '=' '{print $2}'` + + # compare the pgfid(link value ) of each hard links are equal or not + for i in `seq 2 50`; do + TEMP=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/file$i 2>&1 | grep "trusted.pgfid" | gawk -F '=' '{print $2}'` + TEST_IN_LOOP [ $PGFID_FILE1 = $TEMP ] + done + + # check if no of links value is 50 or not + TEST [ $PGFID_FILE1 = "0x00000032" ] + + # unlink file 2 to 50 + for i in `seq 2 50`; do + TEST_IN_LOOP unlink $M0/file$i; + done + + # now check if pgfid value is 1 or not + PGFID_FILE1=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/file1 2>&1 | grep "trusted.pgfid" | gawk -F '=' '{print $2}'`; + + TEST [ $PGFID_FILE1 = "0x00000001" ] + + TEST rm -f $M0/* +} + +##checking pgfid under diff directories +function links_across_directories() +{ + TEST mkdir $M0/dir1 $M0/dir2; + + # create a file in dir1 + TEST touch $M0/dir1/file1; + + # create hard link for file1 in dir2 + TEST ln $M0/dir1/file1 $M0/dir2/file2; + + #first check is to find whether there are two pgfids or not + LINES=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir1/file1 2>&1 | grep "trusted.pgfid" | wc -l` + TEST [ $LINES = 2 ] + + for i in $(seq 1 2); do + HL=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir$i/file$i 2>&1 | grep "trusted.pgfid" | cut -d$'\n' -f$i | cut -d'=' -f2` + TEST_IN_LOOP [ $HL = "0x00000001" ] + done + + #now unlink file2 and check the pgfid of file1 + #1. no. of pgfid should be one + #2. no. of hard link should be one + TEST unlink $M0/dir2/file2 + + LINES=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir1/file1 2>&1 | grep "trusted.pgfid" | wc -l` + TEST [ $LINES == 1 ] + + #next to check is to whether they contain hard link value of one or not + HL=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir1/file1 2>&1 | grep "trusted.pgfid" | cut -d'=' -f2` + TEST [ $HL = "0x00000001" ] + + #rename file under same directory + + TEST touch $M0/r_file1 + PGFID_rfile1=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/r_file1 2>&1 | grep "trusted.pgfid"` + + #cross check whether hard link count is one + HL=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/r_file1 2>&1 | grep "trusted.pgfid" | cut -d'=' -f2` + + TEST [ $HL = "0x00000001" ] + + #now rename the file to r_file1 + TEST mv $M0/r_file1 $M0/r_file2 + + #now check the pgfid hard link count is still one or not + HL=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/r_file2 2>&1 | grep "trusted.pgfid" | cut -d'=' -f2` + + TEST [ $HL = "0x00000001" ] + + #now move the file to a different directory where it has no hard link and check + TEST mkdir $M0/dir3; + TEST mv $M0/r_file2 $M0/dir3; + + #now check the pgfid has changed or not and hard limit is one or not + PGFID_newDir=`getfattr -m "trusted.pgfid.*" -de hex $B0/brick/dir3/r_file2 2>&1 | grep "trusted.pgfid"` + + #now the older pgfid and new pgfid shouldn't match + TEST [ $PGFID_rfile1 != $PGFID_newDir ] + + HL=`getfattr -m "trusted.pgfid" -de hex $B0/brick/dir3/r_file2 2>&1 | grep "trusted.pgfid" | cut -d'=' -f2` + TEST [ $HL = "0x00000001" ] + + TEST touch $M0/dir1/rl_file_1 + ln $M0/dir1/rl_file_1 $M0/dir2/rl_file_2 + mv $M0/dir1/rl_file_1 $M0/dir2 + + #now the there should be just one pgfid for both files + for i in $(seq 1 2); do + NL=`getfattr -m "trusted.pgfid" -de hex $B0/brick/dir2/rl_file_$i 2>&1 | grep "trusted.pgfid"|wc -l ` + TEST_IN_LOOP [ $HL = "0x00000001" ] + done + + #now pgfid of both files should match + P_rl_file_1=`getfattr -m "trusted.pgfid" -de hex $B0/brick/dir2/rl_file_1 2>&1 | grep "trusted.pgfid"` + P_rl_file_2=`getfattr -m "trusted.pgfid" -de hex $B0/brick/dir2/rl_file_2 2>&1 | grep "trusted.pgfid"` + TEST [ $P_rl_file_1 = $P_rl_file_2 ] + + #now the no of hard link should be two for both rl_file_1 and rl_file_2 + for i in $(seq 1 2); do + HL=`getfattr -m "trusted.pgfid" -de hex $B0/brick/dir2/rl_file_$i 2>&1 | grep "trusted.pgfid" | cut -d'=' -f2` + TEST_IN_LOOP [ $HL = "0x00000002" ] + done + + TEST rm -rf $M0/* +} + +__init; +links_in_same_directory; +links_across_directories; + +cleanup diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c index 31826719947..cef2baf599c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-quota.c +++ b/xlators/mgmt/glusterd/src/glusterd-quota.c @@ -260,6 +260,7 @@ glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) runner_add_args (&runner, SBIN_DIR"/glusterfs", "-s", "localhost", "--volfile-id", volname, + "--use-readdirp=no", "-l", DEFAULT_LOG_FILE_DIRECTORY"/quota-crawl.log", mountdir, NULL); diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 0de71a49afe..da8ace953cf 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -1404,25 +1404,27 @@ static int server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *set_dict, void *param) { - char *volname = NULL; - char *path = NULL; - int pump = 0; - xlator_t *xl = NULL; - xlator_t *txl = NULL; - xlator_t *rbxl = NULL; - char transt[16] = {0,}; - char *ptranst = NULL; - char volume_id[64] = {0,}; - char tstamp_file[PATH_MAX] = {0,}; - int ret = 0; - char *xlator = NULL; - char *loglevel = NULL; - char *username = NULL; - char *password = NULL; - char index_basepath[PATH_MAX] = {0}; - char key[1024] = {0}; - glusterd_brickinfo_t *brickinfo = NULL; - char changelog_basepath[PATH_MAX] = {0,}; + char *volname = NULL; + char *path = NULL; + int pump = 0; + xlator_t *xl = NULL; + xlator_t *txl = NULL; + xlator_t *rbxl = NULL; + char transt[16] = {0,}; + char *ptranst = NULL; + char volume_id[64] = {0,}; + char tstamp_file[PATH_MAX] = {0,}; + int ret = 0; + char *xlator = NULL; + char *loglevel = NULL; + char *username = NULL; + char *password = NULL; + char index_basepath[PATH_MAX] = {0}; + char key[1024] = {0}; + glusterd_brickinfo_t *brickinfo = NULL; + char changelog_basepath[PATH_MAX] = {0,}; + gf_boolean_t quota_enabled = _gf_true; + char *value = NULL; brickinfo = param; path = brickinfo->path; @@ -1441,6 +1443,13 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } } + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_QUOTA, &value); + if (value) { + ret = gf_string2boolean (value, "a_enabled); + if (ret) + goto out; + } + xl = volgen_graph_add (graph, "storage/posix", volname); if (!xl) return -1; @@ -1454,6 +1463,10 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, if (ret) return -1; + if (quota_enabled) + xlator_set_option (xl, "update-link-count-parent", + value); + ret = check_and_add_debug_xl (graph, set_dict, volname, "posix"); if (ret) diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index 219a582c9f7..1d8e986314f 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -26,13 +26,167 @@ #include "xlator.h" #include "syscall.h" +inode_t * +posix_resolve (xlator_t *this, inode_table_t *itable, inode_t *parent, + char *bname, struct iatt *iabuf) +{ + inode_t *inode = NULL, *linked_inode = NULL; + int ret = -1; + + ret = posix_istat (this, parent->gfid, bname, iabuf); + if (ret < 0) + goto out; + + inode = inode_find (itable, iabuf->ia_gfid); + if (inode == NULL) { + inode = inode_new (itable); + } + + linked_inode = inode_link (inode, parent, bname, iabuf); + + inode_unref (inode); + +out: + return linked_inode; +} + +int +posix_make_ancestral_node (const char *priv_base_path, char *path, int pathsize, + gf_dirent_t *head, + char *dir_name, struct iatt *iabuf, inode_t *inode, + int type, dict_t *xdata) +{ + gf_dirent_t *entry = NULL; + char real_path[PATH_MAX + 1] = {0, }, len = 0; + loc_t loc = {0, }; + int ret = -1; + + len = strlen (path) + strlen (dir_name) + 1; + if (len > pathsize) { + goto out; + } + + strcat (path, dir_name); + + if (type & POSIX_ANCESTRY_DENTRY) { + entry = gf_dirent_for_name (dir_name); + if (!entry) { + gf_log (THIS->name, GF_LOG_ERROR, + "could not create gf_dirent for entry %s: (%s)", + dir_name, strerror (errno)); + goto out; + } + + entry->d_stat = *iabuf; + entry->inode = inode_ref (inode); + + list_add_tail (&entry->list, &head->list); + strcpy (real_path, priv_base_path); + strcat (real_path, "/"); + strcat (real_path, path); + loc.inode = inode_ref (inode); + uuid_copy (loc.gfid, inode->gfid); + + entry->dict = posix_lookup_xattr_fill (THIS, real_path, &loc, + xdata, iabuf); + loc_wipe (&loc); + } + + ret = 0; + +out: + return ret; +} + +int +posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, + gf_dirent_t *head, int type, uuid_t gfid, + const size_t handle_size, + const char *priv_base_path, inode_table_t *itable, + inode_t **parent, dict_t *xdata) +{ + char *linkname = NULL; /* "../../<gfid[0]>/<gfid[1]/" + "<gfidstr>/<NAME_MAX>" */ + char *dir_handle = NULL; + char *dir_name = NULL; + char *pgfidstr = NULL; + char *saveptr = NULL; + ssize_t len = 0; + inode_t *inode = NULL; + struct iatt iabuf = {0, }; + int ret = -1; + uuid_t tmp_gfid = {0, }; + + if (!path || !parent || !priv_base_path || uuid_is_null (gfid)) { + goto out; + } + + if (__is_root_gfid (gfid)) { + if (parent) { + if (*parent) { + inode_unref (*parent); + } + + *parent = inode_ref (itable->root); + } + + inode = itable->root; + + memset (&iabuf, 0, sizeof (iabuf)); + uuid_copy (iabuf.ia_gfid, inode->gfid); + iabuf.ia_type = inode->ia_type; + + ret = posix_make_ancestral_node (priv_base_path, path, pathsize, + head, "/", &iabuf, inode, type, + xdata); + return ret; + } + + dir_handle = alloca (handle_size); + linkname = alloca (PATH_MAX); + snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s", + priv_base_path, HANDLE_PFX, gfid[0], gfid[1], + uuid_utoa (gfid)); + + len = readlink (dir_handle, linkname, PATH_MAX); + if (len < 0) { + gf_log (this->name, GF_LOG_ERROR, "could not read the link " + "from the gfid handle %s (%s)", dir_handle, + strerror (errno)); + goto out; + } + + linkname[len] = '\0'; + + pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), "/", &saveptr); + dir_name = strtok_r (NULL, "/", &saveptr); + strcat (dir_name, "/"); -#define HANDLE_PFX ".glusterfs" -#define TRASH_DIR "landfill" + uuid_parse (pgfidstr, tmp_gfid); + + ret = posix_make_ancestryfromgfid (this, path, pathsize, head, type, + tmp_gfid, handle_size, + priv_base_path, itable, parent, + xdata); + if (ret < 0) { + goto out; + } -#define UUID0_STR "00000000-0000-0000-0000-000000000000" -#define SLEN(str) (sizeof(str) - 1) + memset (&iabuf, 0, sizeof (iabuf)); + inode = posix_resolve (this, itable, *parent, dir_name, &iabuf); + + ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head, + dir_name, &iabuf, inode, type, xdata); + if (*parent != NULL) { + inode_unref (*parent); + } + + *parent = inode; + +out: + return ret; +} int posix_handle_relpath (xlator_t *this, uuid_t gfid, const char *basename, diff --git a/xlators/storage/posix/src/posix-handle.h b/xlators/storage/posix/src/posix-handle.h index f1163b72795..8874ca2655f 100644 --- a/xlators/storage/posix/src/posix-handle.h +++ b/xlators/storage/posix/src/posix-handle.h @@ -17,9 +17,86 @@ #include <sys/types.h> #include "xlator.h" +#include "gf-dirent.h" +#define HANDLE_PFX ".glusterfs" +#define TRASH_DIR "landfill" -#define LOC_HAS_ABSPATH(loc) ((loc) && (loc->path) && (loc->path[0] == '/')) +#define UUID0_STR "00000000-0000-0000-0000-000000000000" +#define SLEN(str) (sizeof(str) - 1) + +#define LOC_HAS_ABSPATH(loc) (loc && (loc->path) && (loc->path[0] == '/')) + +#define MAKE_PGFID_XATTR_KEY(var, prefix, pgfid) do { \ + var = alloca (strlen (prefix) + UUID_CANONICAL_FORM_LEN + 1); \ + strcpy (var, prefix); \ + strcat (var, uuid_utoa (pgfid)); \ + } while (0) + +#define SET_PGFID_XATTR(path, key, value, flags, op_ret, this, label) do { \ + value = hton32 (value); \ + op_ret = sys_lsetxattr (path, key, &value, sizeof (value), \ + flags); \ + if (op_ret == -1) { \ + op_errno = errno; \ + gf_log (this->name, GF_LOG_WARNING, \ + "setting xattr failed on %s: key = %s (%s)", \ + path, key, strerror (op_errno)); \ + goto label; \ + } \ + } while (0) + + +#define REMOVE_PGFID_XATTR(path, key, op_ret, this, label) do { \ + op_ret = sys_lremovexattr (path, key); \ + if (op_ret == -1) { \ + op_errno = errno; \ + gf_log (this->name, GF_LOG_WARNING, "removing xattr " \ + "failed on %s: key = %s (%s)", path, key, \ + strerror (op_errno)); \ + goto label; \ + } \ + } while (0) + +/* should be invoked holding a lock */ +#define LINK_MODIFY_PGFID_XATTR(path, key, value, flags, op_ret, this, label) do { \ + op_ret = sys_lgetxattr (path, key, &value, sizeof (value)); \ + if (op_ret == -1) { \ + op_errno = errno; \ + if (op_errno == ENOATTR) { \ + value = 1; \ + } else { \ + gf_log (this->name, GF_LOG_WARNING,"getting xattr " \ + "failed on %s: key = %s (%s)", path, key, \ + strerror (op_errno)); \ + goto label; \ + } \ + } else { \ + value = ntoh32 (value); \ + value++; \ + } \ + SET_PGFID_XATTR (path, key, value, flags, op_ret, this, label); \ + } while (0) + +/* should be invoked holding a lock */ +#define UNLINK_MODIFY_PGFID_XATTR(path, key, value, flags, op_ret, this, label) do { \ + op_ret = sys_lgetxattr (path, key, &value, sizeof (value)); \ + if (op_ret == -1) { \ + op_errno = errno; \ + gf_log (this->name, GF_LOG_WARNING, "getting xattr failed on " \ + "%s: key = %s (%s)", path, key, strerror (op_errno)); \ + goto label; \ + } else { \ + value = ntoh32 (value); \ + value--; \ + if (value > 0) { \ + SET_PGFID_XATTR (path, key, value, flags, op_ret, \ + this, label); \ + } else { \ + REMOVE_PGFID_XATTR (path, key, op_ret, this, label); \ + } \ + } \ + } while (0) #define MAKE_REAL_PATH(var, this, path) do { \ var = alloca (strlen (path) + POSIX_BASE_PATH_LEN(this) + 2); \ @@ -27,7 +104,6 @@ strcpy (&var[POSIX_BASE_PATH_LEN(this)], path); \ } while (0) - #define MAKE_HANDLE_PATH(var, this, gfid, base) do { \ int __len; \ __len = posix_handle_path (this, gfid, base, NULL, 0); \ @@ -61,12 +137,12 @@ #define MAKE_INODE_HANDLE(rpath, this, loc, iatt_p) do { \ if (uuid_is_null (loc->gfid)) { \ gf_log (this->name, GF_LOG_ERROR, \ - "null gfid for path %s", loc->path); \ + "null gfid for path %s", (loc)->path); \ break; \ } \ if (LOC_HAS_ABSPATH (loc)) { \ - MAKE_REAL_PATH (rpath, this, loc->path); \ - op_ret = posix_pstat (this, loc->gfid, rpath, iatt_p); \ + MAKE_REAL_PATH (rpath, this, (loc)->path); \ + op_ret = posix_pstat (this, (loc)->gfid, rpath, iatt_p); \ break; \ } \ errno = 0; \ @@ -107,10 +183,20 @@ } while (0) +#define POSIX_ANCESTRY_PATH (1 << 0) +#define POSIX_ANCESTRY_DENTRY (1 << 1) int posix_handle_path (xlator_t *this, uuid_t gfid, const char *basename, char *buf, size_t len); + +int +posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, + gf_dirent_t *head, int type, uuid_t gfid, + const size_t handle_size, + const char *priv_base_path, + inode_table_t *table, inode_t **parent, + dict_t *xdata); int posix_handle_path_safe (xlator_t *this, uuid_t gfid, const char *basename, char *buf, size_t len); diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index e295f8850b4..4db15bf571c 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -102,14 +102,54 @@ out: } static int +_posix_xattr_get_set_from_backend (posix_xattr_filler_t *filler, char *key) +{ + ssize_t xattr_size = -1; + int ret = 0; + char *value = NULL; + + xattr_size = sys_lgetxattr (filler->real_path, key, NULL, 0); + + if (xattr_size > 0) { + value = GF_CALLOC (1, xattr_size + 1, + gf_posix_mt_char); + if (!value) + goto out; + + xattr_size = sys_lgetxattr (filler->real_path, key, value, + xattr_size); + if (xattr_size <= 0) { + gf_log (filler->this->name, GF_LOG_WARNING, + "getxattr failed. path: %s, key: %s", + filler->real_path, key); + GF_FREE (value); + goto out; + } + + value[xattr_size] = '\0'; + ret = dict_set_bin (filler->xattr, key, + value, xattr_size); + if (ret < 0) { + gf_log (filler->this->name, GF_LOG_DEBUG, + "dict set failed. path: %s, key: %s", + filler->real_path, key); + GF_FREE (value); + goto out; + } + } + ret = 0; +out: + return ret; +} + + +static int _posix_xattr_get_set (dict_t *xattr_req, char *key, data_t *data, void *xattrargs) { posix_xattr_filler_t *filler = xattrargs; - char *value = NULL; - ssize_t xattr_size = -1; int ret = -1; char *databuf = NULL; int _fd = -1; @@ -183,35 +223,24 @@ _posix_xattr_get_set (dict_t *xattr_req, "Failed to set dictionary value for %s", key); } - } else { - xattr_size = sys_lgetxattr (filler->real_path, key, NULL, 0); - - if (xattr_size > 0) { - value = GF_CALLOC (1, xattr_size + 1, - gf_posix_mt_char); - if (!value) - return -1; - - xattr_size = sys_lgetxattr (filler->real_path, key, value, - xattr_size); - if (xattr_size <= 0) { - gf_log (filler->this->name, GF_LOG_WARNING, - "getxattr failed. path: %s, key: %s", - filler->real_path, key); - GF_FREE (value); - return -1; - } + } else if (!strcmp (key, GET_ANCESTRY_PATH_KEY)) { + char *path = NULL; + ret = posix_get_ancestry (filler->this, filler->loc->inode, + NULL, &path, POSIX_ANCESTRY_PATH, + &filler->op_errno, xattr_req); + if (ret < 0) { + goto out; + } - value[xattr_size] = '\0'; - ret = dict_set_bin (filler->xattr, key, - value, xattr_size); - if (ret < 0) { - gf_log (filler->this->name, GF_LOG_DEBUG, - "dict set failed. path: %s, key: %s", - filler->real_path, key); - GF_FREE (value); - } + ret = dict_set_dynstr (filler->xattr, GET_ANCESTRY_PATH_KEY, + path); + if (ret < 0) { + GF_FREE (path); + goto out; } + + } else { + ret = _posix_xattr_get_set_from_backend (filler, key); } out: return 0; diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 1a344acbb5a..65b52a07cd5 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -79,7 +79,6 @@ extern char *marker_xattrs[]; #define SET_TO_OLD_FS_ID() #endif - int posix_forget (xlator_t *this, inode_t *inode) { @@ -105,15 +104,18 @@ posix_lookup (call_frame_t *frame, xlator_t *this, char * par_path = NULL; struct iatt postparent = {0,}; int32_t gfidless = 0; + struct posix_private *priv = NULL; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (loc, out); + priv = this->private; + /* The Hidden directory should be for housekeeping purpose and it should not get any gfid on it */ - if (__is_root_gfid (loc->pargfid) && - (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { + if (__is_root_gfid (loc->pargfid) && loc->name + && (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { gf_log (this->name, GF_LOG_WARNING, "Lookup issued on %s, which is not permitted", GF_HIDDEN_PATH); @@ -124,7 +126,7 @@ posix_lookup (call_frame_t *frame, xlator_t *this, op_ret = dict_get_int32 (xdata, GF_GFIDLESS_LOOKUP, &gfidless); op_ret = -1; - if (uuid_is_null (loc->pargfid)) { + if (uuid_is_null (loc->pargfid) || (loc->name == NULL)) { /* nameless lookup */ MAKE_INODE_HANDLE (real_path, this, loc, &buf); } else { @@ -1029,18 +1031,20 @@ int posix_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, dev_t dev, mode_t umask, dict_t *xdata) { - int tmp_fd = 0; - int32_t op_ret = -1; - int32_t op_errno = 0; - char *real_path = 0; - char *par_path = 0; - struct iatt stbuf = { 0, }; - char was_present = 1; - struct posix_private *priv = NULL; - gid_t gid = 0; - struct iatt preparent = {0,}; - struct iatt postparent = {0,}; - void * uuid_req = NULL; + int tmp_fd = 0; + int32_t op_ret = -1; + int32_t op_errno = 0; + char *real_path = 0; + char *par_path = 0; + struct iatt stbuf = { 0, }; + char was_present = 1; + struct posix_private *priv = NULL; + gid_t gid = 0; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + void * uuid_req = NULL; + int32_t nlink_samepgfid = 0; + char *pgfid_xattr_key = NULL; DECLARE_OLD_FS_ID_VAR; @@ -1143,6 +1147,16 @@ post_op: strerror (errno)); } + if (priv->update_pgfid_nlinks) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, + loc->pargfid); + nlink_samepgfid = 1; + + SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, + XATTR_CREATE, op_ret, this, ignore); + } + +ignore: op_ret = posix_entry_create_xattr_set (this, real_path, xdata); if (op_ret) { gf_log (this->name, GF_LOG_ERROR, @@ -1271,7 +1285,6 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, goto out; } #endif - op_ret = posix_acl_xattr_set (this, real_path, xdata); if (op_ret) { gf_log (this->name, GF_LOG_ERROR, @@ -1325,15 +1338,17 @@ int32_t posix_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) { - int32_t op_ret = -1; - int32_t op_errno = 0; - char *real_path = NULL; - char *par_path = NULL; - int32_t fd = -1; - struct iatt stbuf = {0,}; - struct posix_private *priv = NULL; - struct iatt preparent = {0,}; - struct iatt postparent = {0,}; + int32_t op_ret = -1; + int32_t op_errno = 0; + char *real_path = NULL; + char *par_path = NULL; + int32_t fd = -1; + struct iatt stbuf = {0,}; + struct posix_private *priv = NULL; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + char *pgfid_xattr_key = NULL; + int32_t nlink_samepgfid = 0; DECLARE_OLD_FS_ID_VAR; @@ -1371,6 +1386,26 @@ posix_unlink (call_frame_t *frame, xlator_t *this, } } + if (priv->update_pgfid_nlinks && (stbuf.ia_nlink > 1)) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, + loc->pargfid); + LOCK (&loc->inode->lock); + { + UNLINK_MODIFY_PGFID_XATTR (real_path, pgfid_xattr_key, + nlink_samepgfid, 0, op_ret, + this, unlock); + } + unlock: + UNLOCK (&loc->inode->lock); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "modification of " + "parent gfid xattr failed (path:%s gfid:%s)", + real_path, uuid_utoa (loc->inode->gfid)); + goto out; + } + } + op_ret = sys_unlink (real_path); if (op_ret == -1) { op_errno = errno; @@ -1512,16 +1547,18 @@ int posix_symlink (call_frame_t *frame, xlator_t *this, const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata) { - int32_t op_ret = -1; - int32_t op_errno = 0; - char * real_path = 0; - char * par_path = 0; - struct iatt stbuf = { 0, }; - struct posix_private *priv = NULL; - gid_t gid = 0; - char was_present = 1; - struct iatt preparent = {0,}; - struct iatt postparent = {0,}; + int32_t op_ret = -1; + int32_t op_errno = 0; + char * real_path = 0; + char * par_path = 0; + struct iatt stbuf = { 0, }; + struct posix_private *priv = NULL; + gid_t gid = 0; + char was_present = 1; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + char *pgfid_xattr_key = NULL; + int32_t nlink_samepgfid = 0; DECLARE_OLD_FS_ID_VAR; @@ -1582,7 +1619,6 @@ posix_symlink (call_frame_t *frame, xlator_t *this, goto out; } #endif - op_ret = posix_acl_xattr_set (this, real_path, xdata); if (op_ret) { gf_log (this->name, GF_LOG_ERROR, @@ -1590,6 +1626,14 @@ posix_symlink (call_frame_t *frame, xlator_t *this, strerror (errno)); } + if (priv->update_pgfid_nlinks) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, + loc->pargfid); + nlink_samepgfid = 1; + SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, + XATTR_CREATE, op_ret, this, ignore); + } +ignore: op_ret = posix_entry_create_xattr_set (this, real_path, xdata); if (op_ret) { gf_log (this->name, GF_LOG_ERROR, @@ -1636,24 +1680,26 @@ int posix_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - int32_t op_ret = -1; - int32_t op_errno = 0; - char *real_oldpath = NULL; - char *real_newpath = NULL; - char *par_oldpath = NULL; - char *par_newpath = NULL; - struct iatt stbuf = {0, }; - struct posix_private *priv = NULL; - char was_present = 1; - struct iatt preoldparent = {0, }; - struct iatt postoldparent = {0, }; - struct iatt prenewparent = {0, }; - struct iatt postnewparent = {0, }; + int32_t op_ret = -1; + int32_t op_errno = 0; + char *real_oldpath = NULL; + char *real_newpath = NULL; + char *par_oldpath = NULL; + char *par_newpath = NULL; + struct iatt stbuf = {0, }; + struct posix_private *priv = NULL; + char was_present = 1; + struct iatt preoldparent = {0, }; + struct iatt postoldparent = {0, }; + struct iatt prenewparent = {0, }; + struct iatt postnewparent = {0, }; char olddirid[64]; char newdirid[64]; - uuid_t victim = {0}; - int was_dir = 0; - int nlink = 0; + uuid_t victim = {0}; + int was_dir = 0; + int nlink = 0; + char *pgfid_xattr_key = NULL; + int32_t nlink_samepgfid = 0; DECLARE_OLD_FS_ID_VAR; @@ -1718,17 +1764,64 @@ posix_rename (call_frame_t *frame, xlator_t *this, goto out; } - if (IA_ISDIR (oldloc->inode->ia_type)) { + if (IA_ISDIR (oldloc->inode->ia_type)) posix_handle_unset (this, oldloc->inode->gfid, NULL); + + LOCK (&oldloc->inode->lock); + { + if (!IA_ISDIR (oldloc->inode->ia_type) + && priv->update_pgfid_nlinks) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, + PGFID_XATTR_KEY_PREFIX, + oldloc->pargfid); + UNLINK_MODIFY_PGFID_XATTR (real_oldpath, + pgfid_xattr_key, + nlink_samepgfid, 0, + op_ret, + this, unlock); + } + + op_ret = sys_rename (real_oldpath, real_newpath); + if (op_ret == -1) { + op_errno = errno; + gf_log (this->name, + (op_errno == ENOTEMPTY ? GF_LOG_DEBUG + : GF_LOG_ERROR), + "rename of %s to %s failed: %s", + real_oldpath, real_newpath, + strerror (op_errno)); + + if (priv->update_pgfid_nlinks + && !IA_ISDIR (oldloc->inode->ia_type)) { + LINK_MODIFY_PGFID_XATTR (real_oldpath, + pgfid_xattr_key, + nlink_samepgfid, 0, + op_ret, + this, unlock); + } + + goto unlock; + } + + if (!IA_ISDIR (oldloc->inode->ia_type) + && priv->update_pgfid_nlinks) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, + PGFID_XATTR_KEY_PREFIX, + newloc->pargfid); + LINK_MODIFY_PGFID_XATTR (real_newpath, + pgfid_xattr_key, + nlink_samepgfid, 0, + op_ret, + this, unlock); + } } +unlock: + UNLOCK (&oldloc->inode->lock); - op_ret = sys_rename (real_oldpath, real_newpath); - if (op_ret == -1) { - op_errno = errno; - gf_log (this->name, - (op_errno == ENOTEMPTY ? GF_LOG_DEBUG : GF_LOG_ERROR), - "rename of %s to %s failed: %s", - real_oldpath, real_newpath, strerror (op_errno)); + if (op_ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "modification of " + "parent gfid xattr failed (gfid:%s)", + uuid_utoa (oldloc->inode->gfid)); goto out; } @@ -1792,16 +1885,18 @@ int posix_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - int32_t op_ret = -1; - int32_t op_errno = 0; - char *real_oldpath = 0; - char *real_newpath = 0; - char *par_newpath = 0; - struct iatt stbuf = {0, }; - struct posix_private *priv = NULL; - char was_present = 1; - struct iatt preparent = {0,}; - struct iatt postparent = {0,}; + int32_t op_ret = -1; + int32_t op_errno = 0; + char *real_oldpath = 0; + char *real_newpath = 0; + char *par_newpath = 0; + struct iatt stbuf = {0, }; + struct posix_private *priv = NULL; + char was_present = 1; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int32_t nlink_samepgfid = 0; + char *pgfid_xattr_key = NULL; DECLARE_OLD_FS_ID_VAR; @@ -1866,6 +1961,27 @@ posix_link (call_frame_t *frame, xlator_t *this, goto out; } + if (priv->update_pgfid_nlinks) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, + newloc->pargfid); + + LOCK (&newloc->inode->lock); + { + LINK_MODIFY_PGFID_XATTR (real_newpath, pgfid_xattr_key, + nlink_samepgfid, 0, op_ret, + this, unlock); + } + unlock: + UNLOCK (&newloc->inode->lock); + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "modification of " + "parent gfid xattr failed (path:%s gfid:%s)", + real_newpath, uuid_utoa (newloc->inode->gfid)); + goto out; + } + } + op_ret = 0; out: @@ -1932,7 +2048,6 @@ posix_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, } op_ret = 0; - out: SET_TO_OLD_FS_ID (); @@ -1948,20 +2063,23 @@ posix_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { - int32_t op_ret = -1; - int32_t op_errno = 0; - int32_t _fd = -1; - int _flags = 0; - char * real_path = NULL; - char * par_path = NULL; - struct iatt stbuf = {0, }; - struct posix_fd * pfd = NULL; - struct posix_private * priv = NULL; - char was_present = 1; - - gid_t gid = 0; - struct iatt preparent = {0,}; - struct iatt postparent = {0,}; + int32_t op_ret = -1; + int32_t op_errno = 0; + int32_t _fd = -1; + int _flags = 0; + char * real_path = NULL; + char * par_path = NULL; + struct iatt stbuf = {0, }; + struct posix_fd * pfd = NULL; + struct posix_private * priv = NULL; + char was_present = 1; + + gid_t gid = 0; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + + int nlink_samepgfid = 0; + char * pgfid_xattr_key = NULL; DECLARE_OLD_FS_ID_VAR; @@ -2037,7 +2155,6 @@ posix_create (call_frame_t *frame, xlator_t *this, real_path, strerror (op_errno)); } #endif - op_ret = posix_acl_xattr_set (this, real_path, xdata); if (op_ret) { gf_log (this->name, GF_LOG_ERROR, @@ -2045,6 +2162,14 @@ posix_create (call_frame_t *frame, xlator_t *this, strerror (errno)); } + if (priv->update_pgfid_nlinks) { + MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, + loc->pargfid); + nlink_samepgfid = 1; + SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, + XATTR_CREATE, op_ret, this, ignore); + } +ignore: op_ret = posix_entry_create_xattr_set (this, real_path, xdata); if (op_ret) { gf_log (this->name, GF_LOG_ERROR, @@ -2876,6 +3001,335 @@ posix_xattr_get_real_filename (call_frame_t *frame, xlator_t *this, loc_t *loc, return ret; } +int +posix_get_ancestry_directory (xlator_t *this, inode_t *leaf_inode, + gf_dirent_t *head, char **path, int type, + int32_t *op_errno, dict_t *xdata) +{ + ssize_t handle_size = 0; + struct posix_private *priv = NULL; + char dirpath[PATH_MAX+1] = {0,}; + inode_t *inode = NULL; + int ret = -1; + + priv = this->private; + + handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); + + ret = posix_make_ancestryfromgfid (this, dirpath, PATH_MAX + 1, head, + type | POSIX_ANCESTRY_PATH, + leaf_inode->gfid, + handle_size, priv->base_path, + leaf_inode->table, &inode, xdata); + if (ret < 0) + goto out; + + + /* there is already a reference in loc->inode */ + inode_unref (inode); + + if ((type & POSIX_ANCESTRY_PATH) && (path != NULL)) { + if (strcmp (dirpath, "/")) + dirpath[strlen (dirpath) - 1] = '\0'; + + *path = gf_strdup (dirpath); + } + +out: + return ret; +} + +int32_t +posix_links_in_same_directory (char *dirpath, int count, inode_t *leaf_inode, + inode_t *parent, uint64_t ino, + gf_dirent_t *head, char **path, + int type, dict_t *xdata, int32_t *op_errno) +{ + DIR *dirp = NULL; + int op_ret = -1; + struct dirent *entry = NULL; + struct dirent *result = NULL; + inode_t *linked_inode = NULL; + gf_dirent_t *gf_entry = NULL; + char temppath[PATH_MAX+1] = {0,}; + xlator_t *this = NULL; + struct posix_private *priv = NULL; + char *tempv = NULL; + + this = THIS; + + priv = this->private; + + dirp = opendir (dirpath); + if (!dirp) { + *op_errno = errno; + gf_log (this->name, GF_LOG_WARNING, + "could not opendir %s: %s", dirpath, + strerror (*op_errno)); + goto out; + } + + entry = alloca (offsetof(struct dirent, d_name) + NAME_MAX + 1); + if (entry == NULL) + goto out; + + while (count > 0) { + *op_errno = readdir_r (dirp, entry, &result); + if ((result == NULL) || *op_errno) + break; + + if (entry->d_ino != ino) + continue; + + linked_inode = inode_link (leaf_inode, parent, + entry->d_name, NULL); + + GF_ASSERT (linked_inode == leaf_inode); + inode_unref (linked_inode); + + if (type & POSIX_ANCESTRY_DENTRY) { + loc_t loc = {0, }; + + loc.inode = inode_ref (leaf_inode); + uuid_copy (loc.gfid, leaf_inode->gfid); + + strcpy (temppath, dirpath); + strcat (temppath, "/"); + strcat (temppath, entry->d_name); + + gf_entry = gf_dirent_for_name (entry->d_name); + gf_entry->inode = inode_ref (leaf_inode); + gf_entry->dict + = posix_lookup_xattr_fill (this, + temppath, + &loc, xdata, + NULL); + list_add_tail (&gf_entry->list, &head->list); + loc_wipe (&loc); + } + + if (type & POSIX_ANCESTRY_PATH) { + strcpy (temppath, + &dirpath[priv->base_path_length]); + strcat (temppath, "/"); + strcat (temppath, entry->d_name); + if (!*path) { + *path = gf_strdup (temppath); + } else { + /* creating a colon separated */ + /* list of hard links */ + tempv = GF_REALLOC (*path, strlen (*path) + + 1 // ':' + + strlen (temppath) + 1 ); + if (!tempv) { + gf_log (this->name, GF_LOG_WARNING, + "realloc failed on path"); + GF_FREE (*path); + op_ret = -1; + *op_errno = ENOMEM; + goto out; + } + + *path = tempv; + strcat (*path, ":"); + strcat (*path, temppath); + } + } + + count--; + } + +out: + if (dirp) { + op_ret = closedir (dirp); + if (op_ret == -1) { + *op_errno = errno; + gf_log (this->name, GF_LOG_WARNING, + "closedir failed: %s", + strerror (*op_errno)); + } + } + + return op_ret; +} + +int +posix_get_ancestry_non_directory (xlator_t *this, inode_t *leaf_inode, + gf_dirent_t *head, char **path, int type, + int32_t *op_errno, dict_t *xdata) +{ + size_t remaining_size = 0; + char dirpath[PATH_MAX+1] = {0,}, *leaf_path = NULL; + int op_ret = -1, pathlen = -1; + ssize_t handle_size = 0; + char pgfidstr[UUID_CANONICAL_FORM_LEN+1] = {0,}; + uuid_t pgfid = {0, }; + int nlink_samepgfid = 0; + struct stat stbuf = {0,}; + char *list = NULL; + int32_t list_offset = 0; + char key[4096] = {0,}; + struct posix_private *priv = NULL; + ssize_t size = 0; + inode_t *parent = NULL; + loc_t *loc = NULL; + + priv = this->private; + + loc = GF_CALLOC (1, sizeof (*loc), gf_posix_mt_char); + if (loc == NULL) { + op_ret = -1; + *op_errno = ENOMEM; + goto out; + } + + uuid_copy (loc->gfid, leaf_inode->gfid); + + MAKE_INODE_HANDLE (leaf_path, this, loc, NULL); + + GF_FREE (loc); + + size = sys_llistxattr (leaf_path, NULL, 0); + if (size == -1) { + *op_errno = errno; + if ((errno == ENOTSUP) || (errno == ENOSYS)) { + GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, + this->name, GF_LOG_WARNING, + "Extended attributes not " + "supported (try remounting brick" + " with 'user_xattr' flag)"); + + } else { + gf_log (this->name, GF_LOG_WARNING, + "listxattr failed on %s: %s", + leaf_path, strerror (*op_errno)); + + } + + goto out; + } + + if (size == 0) { + op_ret = 0; + goto out; + } + + list = alloca (size + 1); + if (!list) { + *op_errno = errno; + goto out; + } + + size = sys_llistxattr (leaf_path, list, size); + remaining_size = size; + list_offset = 0; + + op_ret = sys_lstat (leaf_path, &stbuf); + if (op_ret == -1) { + *op_errno = errno; + gf_log (this->name, GF_LOG_WARNING, "lstat failed" + " on %s: %s", leaf_path, + strerror (*op_errno)); + goto out; + } + + while (remaining_size > 0) { + if (*(list + list_offset) == '\0') + break; + strcpy (key, list + list_offset); + if (strncmp (key, PGFID_XATTR_KEY_PREFIX, + strlen (PGFID_XATTR_KEY_PREFIX)) != 0) + goto next; + + op_ret = sys_lgetxattr (leaf_path, key, + &nlink_samepgfid, + sizeof(nlink_samepgfid)); + if (op_ret == -1) { + *op_errno = errno; + gf_log (this->name, GF_LOG_ERROR, + "getxattr failed on " + "%s: key = %s (%s)", + leaf_path, + key, + strerror (*op_errno)); + goto out; + } + + nlink_samepgfid = ntoh32 (nlink_samepgfid); + + strcpy (pgfidstr, key + strlen(PGFID_XATTR_KEY_PREFIX)); + uuid_parse (pgfidstr, pgfid); + + handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); + + /* constructing the absolute real path of parent dir */ + strcpy (dirpath, priv->base_path); + pathlen = PATH_MAX + 1 - priv->base_path_length; + + op_ret = posix_make_ancestryfromgfid (this, + dirpath + priv->base_path_length, + pathlen, + head, + POSIX_ANCESTRY_PATH | POSIX_ANCESTRY_DENTRY, + pgfid, + handle_size, + priv->base_path, + leaf_inode->table, + &parent, xdata); + if (op_ret < 0) { + goto next; + } + + dirpath[strlen (dirpath) - 1] = '\0'; + + posix_links_in_same_directory (dirpath, nlink_samepgfid, + leaf_inode, + parent, stbuf.st_ino, head, + path, type, xdata, op_errno); + + if (parent != NULL) { + inode_unref (parent); + parent = NULL; + } + + next: + remaining_size -= strlen (key) + 1; + list_offset += strlen (key) + 1; + } /* while (remaining_size > 0) */ + + op_ret = 0; + +out: + return op_ret; +} + +int +posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, + gf_dirent_t *head, char **path, int type, int32_t *op_errno, + dict_t *xdata) +{ + int ret = -1; + struct posix_private *priv = NULL; + + priv = this->private; + + if (!priv->update_pgfid_nlinks) + goto out; + + if (IA_ISDIR (leaf_inode->ia_type)) { + ret = posix_get_ancestry_directory (this, leaf_inode, + head, path, type, op_errno, + xdata); + } else { + ret = posix_get_ancestry_non_directory (this, leaf_inode, + head, path, type, + op_errno, xdata); + } + +out: + return ret; +} + /** * posix_getxattr - this function returns a dictionary with all the * key:value pair present as xattr. used for @@ -2885,23 +3339,23 @@ int32_t posix_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { - struct posix_private *priv = NULL; - int32_t op_ret = -1; - int32_t op_errno = 0; - int32_t list_offset = 0; - ssize_t size = 0; - size_t remaining_size = 0; - char key[4096] = {0,}; - char host_buf[1024] = {0,}; - char *value = NULL; - char *list = NULL; - char *real_path = NULL; - dict_t *dict = NULL; - char *file_contents = NULL; - int ret = -1; - char *path = NULL; - char *rpath = NULL; - char *dyn_rpath = NULL; + struct posix_private *priv = NULL; + int32_t op_ret = -1; + int32_t op_errno = 0; + char host_buf[1024] = {0,}; + char *value = NULL; + char *real_path = NULL; + dict_t *dict = NULL; + char *file_contents = NULL; + int ret = -1; + char *path = NULL; + char *rpath = NULL; + char *dyn_rpath = NULL; + ssize_t size = 0; + char *list = NULL; + int32_t list_offset = 0; + size_t remaining_size = 0; + char key[4096] = {0,}; DECLARE_OLD_FS_ID_VAR; @@ -3045,6 +3499,31 @@ posix_getxattr (call_frame_t *frame, xlator_t *this, goto done; } + if (loc->inode && name + && (strcmp (name, GET_ANCESTRY_PATH_KEY) == 0)) { + int type = POSIX_ANCESTRY_PATH; + + op_ret = posix_get_ancestry (this, loc->inode, NULL, + &path, type, &op_errno, + xdata); + if (op_ret < 0) { + op_ret = -1; + op_errno = ENODATA; + goto out; + } + + op_ret = dict_set_dynstr (dict, GET_ANCESTRY_PATH_KEY, path); + if (op_ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "could not get " + "value for key (%s)", GET_ANCESTRY_PATH_KEY); + GF_FREE (path); + op_errno = -op_ret; + op_ret = -1; + } + + goto done; + } + if (name) { strcpy (key, name); @@ -3189,8 +3668,9 @@ out: STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, NULL); - if (dict) + if (dict) { dict_unref (dict); + } return 0; } @@ -4322,15 +4802,14 @@ int32_t posix_do_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, int whichop, dict_t *dict) { - struct posix_fd *pfd = NULL; - DIR *dir = NULL; - int ret = -1; - int count = 0; - int32_t op_ret = -1; - int32_t op_errno = 0; - gf_dirent_t entries; - int32_t skip_dirs = 0; - + struct posix_fd *pfd = NULL; + DIR *dir = NULL; + int ret = -1; + int count = 0; + int32_t op_ret = -1; + int32_t op_errno = 0; + gf_dirent_t entries; + int32_t skip_dirs = 0; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); @@ -4409,6 +4888,32 @@ int32_t posix_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *dict) { + gf_dirent_t entries; + int32_t op_ret = -1, op_errno = 0; + gf_dirent_t *entry = NULL; + + + if ((dict != NULL) && (dict_get (dict, GET_ANCESTRY_DENTRY_KEY))) { + INIT_LIST_HEAD (&entries.list); + + op_ret = posix_get_ancestry (this, fd->inode, &entries, NULL, + POSIX_ANCESTRY_DENTRY, + &op_errno, dict); + if (op_ret >= 0) { + op_ret = 0; + + list_for_each_entry (entry, &entries.list, list) { + op_ret++; + } + } + + STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, &entries, + NULL); + + gf_dirent_free (&entries); + return 0; + } + posix_do_readdir (frame, this, fd, size, off, GF_FOP_READDIRP, dict); return 0; } @@ -4635,6 +5140,9 @@ reconfigure (xlator_t *this, dict_t *options) else posix_aio_off (this); + GF_OPTION_RECONF ("update-link-count-parent", priv->update_pgfid_nlinks, + options, bool, out); + GF_OPTION_RECONF ("node-uuid-pathinfo", priv->node_uuid_pathinfo, options, bool, out); @@ -4912,6 +5420,24 @@ init (xlator_t *this) "for every open)"); } + tmp_data = dict_get (this->options, "update-link-count-parent"); + if (tmp_data) { + if (gf_string2boolean (tmp_data->data, + &_private->update_pgfid_nlinks) == -1) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "wrong value provided for " + "'update-link-count-parent'"); + goto out; + } + if (_private->update_pgfid_nlinks) + gf_log (this->name, GF_LOG_DEBUG, + "update-link-count-parent is enabled. Thus for each " + "file an extended attribute representing the " + "number of hardlinks for that file within the " + "same parent directory is set."); + } + ret = dict_get_str (this->options, "glusterd-uuid", &guuid); if (!ret) { if (uuid_parse (guuid, _private->glusterd_uuid)) @@ -5203,5 +5729,10 @@ struct volume_options options[] = { .description = "Num of usecs to wait for aggregating fsync" " requests", }, + { .key = {"update-link-count-parent"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "false", + .description = "Enable placeholders for gfid to path conversion" + }, { .key = {NULL} } }; diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index 3121db2717e..d579bf673db 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -52,6 +52,12 @@ #define VECTOR_SIZE 64 * 1024 /* vector size 64KB*/ #define MAX_NO_VECT 1024 + +#define POSIX_GFID_HANDLE_SIZE(base_path_len) (base_path_len + SLEN("/") \ + + SLEN(HANDLE_PFX) + SLEN("/") \ + + SLEN("00/") \ + + SLEN("00/") + SLEN(UUID0_STR) + 1) /* '\0' */; + /** * posix_fd - internal structure common to file and directory fd's */ @@ -146,6 +152,7 @@ struct posix_private { } batch_fsync_mode; uint32_t batch_fsync_delay_usec; + gf_boolean_t update_pgfid_nlinks; /* seconds to sleep between health checks */ uint32_t health_check_interval; @@ -205,4 +212,8 @@ __posix_fd_set_odirect (fd_t *fd, struct posix_fd *pfd, int opflags, void posix_spawn_health_check_thread (xlator_t *this); void *posix_fsyncer (void *); +int +posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, + gf_dirent_t *head, char **path, int type, int32_t *op_errno, + dict_t *xdata); #endif /* _POSIX_H */ |