diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-entry-ops.c')
| -rw-r--r-- | xlators/storage/posix/src/posix-entry-ops.c | 445 |
1 files changed, 295 insertions, 150 deletions
diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c index 17fab3e6e9c..8cc3ccf8c00 100644 --- a/xlators/storage/posix/src/posix-entry-ops.c +++ b/xlators/storage/posix/src/posix-entry-ops.c @@ -26,7 +26,6 @@ #include <signal.h> #include <sys/uio.h> #include <unistd.h> -#include <ftw.h> #ifndef GF_BSD_HOST_OS #include <alloca.h> @@ -36,32 +35,26 @@ #include <fcntl.h> #endif /* HAVE_LINKAT */ -#include "glusterfs.h" -#include "checksum.h" -#include "dict.h" -#include "logging.h" +#include <glusterfs/dict.h> +#include <glusterfs/logging.h> #include "posix.h" #include "posix-handle.h" -#include "xlator.h" -#include "defaults.h" -#include "common-utils.h" -#include "compat-errno.h" -#include "compat.h" -#include "byte-order.h" -#include "syscall.h" -#include "statedump.h" -#include "locking.h" -#include "timer.h" +#include <glusterfs/compat-errno.h> +#include <glusterfs/compat.h> +#include <glusterfs/byte-order.h> +#include <glusterfs/syscall.h> +#include <glusterfs/statedump.h> +#include <glusterfs/locking.h> +#include <glusterfs/timer.h> #include "glusterfs3-xdr.h" -#include "hashfn.h" #include "posix-aio.h" -#include "glusterfs-acl.h" +#include <glusterfs/glusterfs-acl.h> #include "posix-messages.h" #include "posix-metadata.h" -#include "events.h" +#include <glusterfs/events.h> #include "posix-gfid-path.h" -#include "compat-uuid.h" -#include "syncop.h" +#include <glusterfs/compat-uuid.h> +#include <glusterfs/syncop.h> extern char *marker_xattrs[]; #define ALIGN_SIZE 4096 @@ -93,7 +86,7 @@ extern char *marker_xattrs[]; #endif -gf_boolean_t +static gf_boolean_t posix_symlinks_match(xlator_t *this, loc_t *loc, uuid_t gfid) { struct posix_private *priv = NULL; @@ -114,7 +107,7 @@ posix_symlinks_match(xlator_t *this, loc_t *loc, uuid_t gfid) loc->pargfid[0], loc->pargfid[1], uuid_utoa(loc->pargfid), loc->name); - MAKE_HANDLE_GFID_PATH(dir_handle, this, gfid, NULL); + MAKE_HANDLE_GFID_PATH(dir_handle, this, gfid); len = sys_readlink(dir_handle, linkname_actual, PATH_MAX); if (len < 0 || len == PATH_MAX) { if (len == PATH_MAX) { @@ -136,12 +129,12 @@ out: return ret; } -dict_t * +static dict_t * posix_dict_set_nlink(dict_t *req, dict_t *res, int32_t nlink) { int ret = -1; - if (req == NULL || !dict_get(req, GF_REQUEST_LINK_COUNT_XDATA)) + if (req == NULL || !dict_get_sizen(req, GF_REQUEST_LINK_COUNT_XDATA)) goto out; if (res == NULL) @@ -183,6 +176,7 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) struct posix_private *priv = NULL; posix_inode_ctx_t *ctx = NULL; int ret = 0; + int dfd = -1; VALIDATE_OR_GOTO(frame, out); VALIDATE_OR_GOTO(this, out); @@ -204,7 +198,20 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) goto out; } - op_ret = dict_get_int32(xdata, GF_GFIDLESS_LOOKUP, &gfidless); +#ifdef __NetBSD__ + /* Same for NetBSD's .attribute directory */ + if (__is_root_gfid(loc->pargfid) && loc->name && + (strcmp(loc->name, ".attribute") == 0)) { + gf_msg(this->name, GF_LOG_WARNING, EPERM, P_MSG_LOOKUP_NOT_PERMITTED, + "Lookup issued on .attribute," + " which is not permitted"); + op_errno = EPERM; + op_ret = -1; + goto out; + } +#endif /* __NetBSD__ */ + + op_ret = dict_get_int32_sizen(xdata, GF_GFIDLESS_LOOKUP, &gfidless); op_ret = -1; if (gf_uuid_is_null(loc->pargfid) || (loc->name == NULL)) { /* nameless lookup */ @@ -239,12 +246,12 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) if (!op_errno) op_errno = ESTALE; loc_gfid(loc, gfid); - MAKE_HANDLE_ABSPATH(gfid_path, this, gfid); - ret = sys_stat(gfid_path, &statbuf); + MAKE_HANDLE_ABSPATH_FD(gfid_path, this, gfid, dfd); + ret = sys_fstatat(dfd, gfid_path, &statbuf, 0); if (ret == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) /*Don't unset if it was a symlink to a dir.*/ goto parent; - ret = sys_lstat(gfid_path, &statbuf); + ret = sys_fstatat(dfd, gfid_path, &statbuf, AT_SYMLINK_NOFOLLOW); if (ret == 0 && statbuf.st_nlink == 1) { gf_msg(this->name, GF_LOG_WARNING, op_errno, P_MSG_HANDLE_DELETE, @@ -263,7 +270,7 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) posix_cs_maintenance(this, NULL, loc, NULL, &buf, real_path, xdata, &xattr, _gf_true); - if (dict_get(xdata, GF_CLEAN_WRITE_PROTECTION)) { + if (dict_get_sizen(xdata, GF_CLEAN_WRITE_PROTECTION)) { ret = sys_lremovexattr(real_path, GF_PROTECT_FROM_EXTERNAL_WRITES); if (ret == -1 && (errno != ENODATA && errno != ENOATTR)) gf_msg(this->name, GF_LOG_ERROR, P_MSG_XATTR_NOT_REMOVED, errno, @@ -272,6 +279,7 @@ posix_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) } } + posix_update_iatt_buf(&buf, -1, real_path, xdata); if (priv->update_pgfid_nlinks) { if (!gf_uuid_is_null(loc->pargfid) && !IA_ISDIR(buf.ia_type)) { MAKE_PGFID_XATTR_KEY(pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, @@ -336,6 +344,38 @@ out: return 0; } +static int32_t +posix_set_gfid2path_xattr(xlator_t *this, const char *path, uuid_t pgfid, + const char *bname) +{ + char xxh64[GF_XXH64_DIGEST_LENGTH * 2 + 1] = { + 0, + }; + char pgfid_bname[1024] = { + 0, + }; + char *key = NULL; + const size_t key_size = GFID2PATH_XATTR_KEY_PREFIX_LENGTH + + GF_XXH64_DIGEST_LENGTH * 2 + 1; + int ret = 0; + int len; + + len = snprintf(pgfid_bname, sizeof(pgfid_bname), "%s/%s", uuid_utoa(pgfid), + bname); + gf_xxh64_wrapper((unsigned char *)pgfid_bname, len, + GF_XXHSUM64_DEFAULT_SEED, xxh64); + key = alloca(key_size); + snprintf(key, key_size, GFID2PATH_XATTR_KEY_PREFIX "%s", xxh64); + + ret = sys_lsetxattr(path, key, pgfid_bname, len, XATTR_CREATE); + if (ret == -1) { + gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_PGFID_OP, + "setting gfid2path xattr failed on %s: key = %s ", path, key); + } + + return ret; +} + 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) @@ -375,7 +415,8 @@ posix_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, priv = this->private; VALIDATE_OR_GOTO(priv, out); - GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, out); + GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, + uuid_req, out); MAKE_ENTRY_HANDLE(real_path, par_path, this, loc, NULL); mode_bit = (priv->create_mask & mode) | priv->force_create_mode; @@ -407,16 +448,22 @@ posix_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, /* Check if the 'gfid' already exists, because this mknod may be an internal call from distribute for creating 'linkfile', and that linkfile may be for a hardlinked file */ - if (dict_get(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) { - dict_del(xdata, GLUSTERFS_INTERNAL_FOP_KEY); - op_ret = dict_get_gfuuid(xdata, "gfid-req", &uuid_req); - if (op_ret) { - gf_msg_debug(this->name, 0, - "failed to get the gfid from " - "dict for %s", - loc->path); - goto real_op; + if (dict_get_sizen(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) { + dict_del_sizen(xdata, GLUSTERFS_INTERNAL_FOP_KEY); + /* trash xlator did not bring the uuid_via the call + * to GFID_NULL_CHECK_AND_GOTO() above. + * Fetch it explicitly here. + */ + if (frame->root->pid == GF_SERVER_PID_TRASH) { + op_ret = dict_get_gfuuid(xdata, "gfid-req", &uuid_req); + if (op_ret) { + gf_msg_debug(this->name, 0, + "failed to get the gfid from dict for %s", + loc->path); + goto real_op; + } } + op_ret = posix_create_link_if_gfid_exists(this, uuid_req, real_path, loc->inode->table); if (!op_ret) { @@ -499,7 +546,7 @@ post_op: posix_set_gfid2path_xattr(this, real_path, loc->pargfid, loc->name); } - op_ret = posix_entry_create_xattr_set(this, real_path, xdata); + op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata); if (op_ret) { if (errno != EEXIST) gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, @@ -574,6 +621,7 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, int32_t op_errno = 0; char *real_path = NULL, *gfid_path = NULL; char *par_path = NULL, *xattr_name = NULL; + int xattr_name_len; struct iatt stbuf = { 0, }; @@ -591,13 +639,9 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, }; ssize_t size = 0; dict_t *xdata_rsp = NULL; - void *disk_xattr = NULL; + char *disk_xattr = NULL; data_t *arg_data = NULL; char pgfid[GF_UUID_BUF_SIZE] = {0}; - char value_buf[4096] = { - 0, - }; - gf_boolean_t have_val = _gf_false; mode_t mode_bit = 0; DECLARE_OLD_FS_ID_VAR; @@ -619,9 +663,23 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto out; } +#ifdef __NetBSD__ + /* Same for NetBSD's .attribute directory */ + if (__is_root_gfid(loc->pargfid) && + (strcmp(loc->name, ".attribute") == 0)) { + gf_msg(this->name, GF_LOG_WARNING, EPERM, P_MSG_MKDIR_NOT_PERMITTED, + "mkdir issued on .attribute, which" + "is not permitted"); + op_errno = EPERM; + op_ret = -1; + goto out; + } +#endif + priv = this->private; VALIDATE_OR_GOTO(priv, out); - GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, out); + GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, + uuid_req, out); DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); MAKE_ENTRY_HANDLE(real_path, par_path, this, loc, NULL); @@ -631,11 +689,6 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto out; } - if (loc->parent) - gf_uuid_unparse(loc->parent->gfid, pgfid); - else - gf_uuid_unparse(loc->pargfid, pgfid); - gid = frame->root->gid; op_ret = posix_pstat(this, loc->inode, NULL, real_path, &stbuf, _gf_false); @@ -647,8 +700,7 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode = posix_override_umask(mode, mode_bit); if (xdata) { - op_ret = dict_get_gfuuid(xdata, "gfid-req", &uuid_req); - if (!op_ret && !gf_uuid_compare(stbuf.ia_gfid, uuid_req)) { + if (!gf_uuid_compare(stbuf.ia_gfid, uuid_req)) { op_ret = -1; op_errno = EEXIST; goto out; @@ -658,12 +710,13 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, if (!gf_uuid_is_null(uuid_req)) { op_ret = posix_istat(this, loc->inode, uuid_req, NULL, &stbuf); if ((op_ret == 0) && IA_ISDIR(stbuf.ia_type)) { - size = posix_handle_path(this, uuid_req, NULL, NULL, 0); - if (size > 0) - gfid_path = alloca(size); - - if (gfid_path) - posix_handle_path(this, uuid_req, NULL, gfid_path, size); + gfid_path = alloca(PATH_MAX); + size = posix_handle_path(this, uuid_req, NULL, gfid_path, PATH_MAX); + if (size <= 0) { + op_errno = ESTALE; + op_ret = -1; + goto out; + } if (frame->root->pid != GF_CLIENT_PID_SELF_HEALD) { gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_DIR_OF_SAME_ID, @@ -712,25 +765,53 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode |= S_ISGID; } - op_ret = dict_get_str(xdata, GF_PREOP_PARENT_KEY, &xattr_name); + op_ret = dict_get_str_sizen(xdata, GF_PREOP_PARENT_KEY, &xattr_name); if (xattr_name != NULL) { - arg_data = dict_get(xdata, xattr_name); + xattr_name_len = strlen(xattr_name); + arg_data = dict_getn(xdata, xattr_name, xattr_name_len); if (arg_data) { - size = sys_lgetxattr(par_path, xattr_name, value_buf, - sizeof(value_buf) - 1); - if (size >= 0) { - have_val = _gf_true; - } else { - if (errno == ERANGE) { - gf_msg(this->name, GF_LOG_INFO, errno, + if (loc->parent) + gf_uuid_unparse(loc->parent->gfid, pgfid); + else + gf_uuid_unparse(loc->pargfid, pgfid); + + size = 256; + disk_xattr = GF_MALLOC(size + 1, gf_posix_mt_char); + if (!disk_xattr) { + op_ret = -1; + op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, errno, + P_MSG_PREOP_CHECK_FAILED, + "mkdir (%s/%s): GF_MALLOC failed during" + " preop of mkdir (%s)", + pgfid, loc->name, real_path); + goto out; + } + disk_xattr[size] = '\0'; + + size = sys_lgetxattr(par_path, xattr_name, disk_xattr, size); + if (size == -1) { + if (disk_xattr) { + GF_FREE(disk_xattr); + disk_xattr = NULL; + } + if (errno != ERANGE) { + op_ret = -1; + op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_PREOP_CHECK_FAILED, - "mkdir (%s/%s): getxattr on key " - "(%s) path (%s) failed due to " - " buffer overflow", - pgfid, loc->name, xattr_name, par_path); - size = sys_lgetxattr(par_path, xattr_name, NULL, 0); + "mkdir (%s/%s): getxattr failed during" + " preop of mkdir (%s).", + pgfid, loc->name, real_path); + goto out; } - if (size < 0) { + gf_msg(this->name, GF_LOG_INFO, errno, P_MSG_PREOP_CHECK_FAILED, + "mkdir (%s/%s): getxattr on key " + "(%s) path (%s) failed due to " + " buffer overflow", + pgfid, loc->name, xattr_name, par_path); + size = sys_lgetxattr(par_path, xattr_name, NULL, 0); + if (size == -1) { op_ret = -1; op_errno = errno; gf_msg(this->name, GF_LOG_ERROR, errno, @@ -740,23 +821,20 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, pgfid, loc->name, xattr_name, par_path); goto out; } - } - disk_xattr = alloca(size); - if (disk_xattr == NULL) { - op_ret = -1; - op_errno = errno; - gf_msg(this->name, GF_LOG_ERROR, errno, - P_MSG_PREOP_CHECK_FAILED, - "mkdir (%s/%s): alloca failed during" - " preop of mkdir (%s)", - pgfid, loc->name, real_path); - goto out; - } - if (have_val) { - memcpy(disk_xattr, value_buf, size); - } else { + disk_xattr = GF_MALLOC(size + 1, gf_posix_mt_char); + if (!disk_xattr) { + op_ret = -1; + op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, errno, + P_MSG_PREOP_CHECK_FAILED, + "mkdir (%s/%s): GF_MALLOC failed during" + " preop of mkdir (%s)", + pgfid, loc->name, real_path); + goto out; + } + disk_xattr[size] = '\0'; size = sys_lgetxattr(par_path, xattr_name, disk_xattr, size); - if (size < 0) { + if (size == -1) { op_errno = errno; gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_PREOP_CHECK_FAILED, @@ -796,10 +874,10 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto out; } - dict_del(xdata, xattr_name); + dict_deln(xdata, xattr_name, xattr_name_len); } - dict_del(xdata, GF_PREOP_PARENT_KEY); + dict_del_sizen(xdata, GF_PREOP_PARENT_KEY); } op_ret = sys_mkdir(real_path, mode); @@ -827,7 +905,7 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, "setting ACLs on %s failed ", real_path); } - op_ret = posix_entry_create_xattr_set(this, real_path, xdata); + op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata); if (op_ret) { gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, "setting xattrs on %s failed", real_path); @@ -869,6 +947,9 @@ posix_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, out: SET_TO_OLD_FS_ID(); + if (disk_xattr) + GF_FREE(disk_xattr); + if (op_ret < 0) { if (entry_created) sys_rmdir(real_path); @@ -887,7 +968,7 @@ out: return 0; } -int +static int posix_add_unlink_to_ctx(inode_t *inode, xlator_t *this, char *unlink_path) { uint64_t ctx = GF_UNLINK_FALSE; @@ -895,7 +976,7 @@ posix_add_unlink_to_ctx(inode_t *inode, xlator_t *this, char *unlink_path) if (!unlink_path) { gf_msg(this->name, GF_LOG_ERROR, ENOMEM, P_MSG_UNLINK_FAILED, - "Creation of unlink entry failed for gfid: %s", unlink_path); + "Creation of unlink entry failed"); ret = -1; goto out; } @@ -910,17 +991,17 @@ out: return ret; } -int32_t +static int32_t posix_move_gfid_to_unlink(xlator_t *this, uuid_t gfid, loc_t *loc) { char *unlink_path = NULL; char *gfid_path = NULL; - int ret = 0; + int ret = -1; struct posix_private *priv_posix = NULL; priv_posix = (struct posix_private *)this->private; - MAKE_HANDLE_GFID_PATH(gfid_path, this, gfid, NULL); + MAKE_HANDLE_GFID_PATH(gfid_path, this, gfid); POSIX_GET_FILE_UNLINK_PATH(priv_posix->base_path, loc->inode->gfid, unlink_path); @@ -944,7 +1025,7 @@ out: return ret; } -int32_t +static int32_t posix_unlink_gfid_handle_and_entry(call_frame_t *frame, xlator_t *this, const char *real_path, struct iatt *stbuf, int32_t *op_errno, loc_t *loc, @@ -987,6 +1068,8 @@ posix_unlink_gfid_handle_and_entry(call_frame_t *frame, xlator_t *this, */ ret = posix_pstat(this, NULL, loc->gfid, real_path, &prebuf, _gf_true); if (ret) { + UNLOCK(&loc->inode->lock); + locked = _gf_false; gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, "lstat on %s failed", real_path); goto err; @@ -995,6 +1078,12 @@ posix_unlink_gfid_handle_and_entry(call_frame_t *frame, xlator_t *this, /* Unlink the actual file */ ret = sys_unlink(real_path); + + if (locked) { + UNLOCK(&loc->inode->lock); + locked = _gf_false; + } + if (ret == -1) { if (op_errno) *op_errno = errno; @@ -1003,11 +1092,6 @@ posix_unlink_gfid_handle_and_entry(call_frame_t *frame, xlator_t *this, goto err; } - if (locked) { - UNLOCK(&loc->inode->lock); - locked = _gf_false; - } - if (update_ctime) { posix_set_ctime(frame, this, NULL, -1, loc->inode, stbuf); } @@ -1027,10 +1111,10 @@ err: return -1; } -gf_boolean_t +static gf_boolean_t posix_skip_non_linkto_unlink(dict_t *xdata, loc_t *loc, char *key, - const char *linkto_xattr, struct iatt *stbuf, - const char *real_path) + const int keylen, const char *linkto_xattr, + struct iatt *stbuf, const char *real_path) { gf_boolean_t skip_unlink = _gf_false; gf_boolean_t is_dht_linkto_file = _gf_false; @@ -1038,7 +1122,7 @@ posix_skip_non_linkto_unlink(dict_t *xdata, loc_t *loc, char *key, ssize_t xattr_size = -1; int op_ret = -1; - op_ret = dict_get_int32(xdata, key, &unlink_if_linkto); + op_ret = dict_get_int32n(xdata, key, keylen, &unlink_if_linkto); if (!op_ret && unlink_if_linkto) { is_dht_linkto_file = IS_DHT_LINKFILE_MODE(stbuf); @@ -1049,11 +1133,11 @@ posix_skip_non_linkto_unlink(dict_t *xdata, loc_t *loc, char *key, xattr_size = sys_lgetxattr(real_path, linkto_xattr, NULL, 0); + UNLOCK(&loc->inode->lock); + if (xattr_size <= 0) skip_unlink = _gf_true; - UNLOCK(&loc->inode->lock); - gf_msg("posix", GF_LOG_INFO, 0, P_MSG_XATTR_STATUS, "linkto_xattr status: %" PRIu32 " for %s", skip_unlink, real_path); @@ -1061,6 +1145,38 @@ posix_skip_non_linkto_unlink(dict_t *xdata, loc_t *loc, char *key, return skip_unlink; } +static int32_t +posix_remove_gfid2path_xattr(xlator_t *this, const char *path, uuid_t pgfid, + const char *bname) +{ + char xxh64[GF_XXH64_DIGEST_LENGTH * 2 + 1] = { + 0, + }; + char pgfid_bname[1024] = { + 0, + }; + int ret = 0; + char *key = NULL; + const size_t key_size = GFID2PATH_XATTR_KEY_PREFIX_LENGTH + + GF_XXH64_DIGEST_LENGTH * 2 + 1; + int len; + + len = snprintf(pgfid_bname, sizeof(pgfid_bname), "%s/%s", uuid_utoa(pgfid), + bname); + gf_xxh64_wrapper((unsigned char *)pgfid_bname, len, + GF_XXHSUM64_DEFAULT_SEED, xxh64); + key = alloca(key_size); + snprintf(key, key_size, GFID2PATH_XATTR_KEY_PREFIX "%s", xxh64); + + ret = sys_lremovexattr(path, key); + if (ret == -1) { + gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_PGFID_OP, + "removing gfid2path xattr failed on %s: key = %s", path, key); + } + + return ret; +} + int32_t posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) @@ -1070,6 +1186,7 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, char *real_path = NULL; char *par_path = NULL; int32_t fd = -1; + int ret = -1; struct iatt stbuf = { 0, }; @@ -1089,9 +1206,6 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, int32_t skip_unlink = 0; int32_t fdstat_requested = 0; dict_t *unwind_dict = NULL; - void *uuid = NULL; - char uuid_str[GF_UUID_BUF_SIZE] = {0}; - char gfid_str[GF_UUID_BUF_SIZE] = {0}; gf_boolean_t get_link_count = _gf_false; posix_inode_ctx_t *ctx = NULL; @@ -1121,22 +1235,8 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, priv = this->private; - op_ret = dict_get_ptr(xdata, TIER_LINKFILE_GFID, &uuid); - - if (!op_ret && gf_uuid_compare(uuid, stbuf.ia_gfid)) { - op_errno = ENOENT; - op_ret = -1; - gf_uuid_unparse(uuid, uuid_str); - gf_uuid_unparse(stbuf.ia_gfid, gfid_str); - gf_msg_debug(this->name, op_errno, - "Mismatch in gfid for path " - "%s. Aborting the unlink. loc->gfid = %s, " - "stbuf->ia_gfid = %s", - real_path, uuid_str, gfid_str); - goto out; - } - - op_ret = dict_get_int32(xdata, DHT_SKIP_OPEN_FD_UNLINK, &check_open_fd); + op_ret = dict_get_int32_sizen(xdata, DHT_SKIP_OPEN_FD_UNLINK, + &check_open_fd); if (!op_ret && check_open_fd) { LOCK(&loc->inode->lock); @@ -1163,10 +1263,8 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, * we don't need to call second function, skip unlink. */ skip_unlink = posix_skip_non_linkto_unlink( - xdata, loc, DHT_SKIP_NON_LINKTO_UNLINK, DHT_LINKTO, &stbuf, real_path); - skip_unlink = skip_unlink || posix_skip_non_linkto_unlink( - xdata, loc, TIER_SKIP_NON_LINKTO_UNLINK, - TIER_LINKTO, &stbuf, real_path); + xdata, loc, DHT_SKIP_NON_LINKTO_UNLINK, + SLEN(DHT_SKIP_NON_LINKTO_UNLINK), DHT_LINKTO, &stbuf, real_path); if (skip_unlink) { op_ret = -1; op_errno = EBUSY; @@ -1174,7 +1272,7 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, } if (IA_ISREG(loc->inode->ia_type) && xdata && - dict_get(xdata, DHT_IATT_IN_XDATA_KEY)) { + dict_get_sizen(xdata, DHT_IATT_IN_XDATA_KEY)) { fdstat_requested = 1; } @@ -1234,7 +1332,15 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, goto out; } - if (xdata && dict_get(xdata, GET_LINK_COUNT)) + if (xdata && dict_get_sizen(xdata, GF_GET_FILE_BLOCK_COUNT)) { + ret = dict_set_uint64(unwind_dict, GF_GET_FILE_BLOCK_COUNT, + stbuf.ia_blocks); + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_SET_XDATA_FAIL, + "Failed to set %s in rsp dict", GF_GET_FILE_BLOCK_COUNT); + } + + if (xdata && dict_get_sizen(xdata, GET_LINK_COUNT)) get_link_count = _gf_true; op_ret = posix_unlink_gfid_handle_and_entry(frame, this, real_path, &stbuf, &op_errno, loc, get_link_count, @@ -1336,6 +1442,19 @@ posix_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, goto out; } +#ifdef __NetBSD__ + /* Same for NetBSD's .attribute directory */ + if (__is_root_gfid(loc->pargfid) && + (strcmp(loc->name, ".attribute") == 0)) { + gf_msg(this->name, GF_LOG_WARNING, EPERM, P_MSG_RMDIR_NOT_PERMITTED, + "rmdir issued on .attribute, which" + "is not permitted"); + op_errno = EPERM; + op_ret = -1; + goto out; + } +#endif + priv = this->private; MAKE_ENTRY_HANDLE(real_path, par_path, this, loc, &stbuf); @@ -1355,18 +1474,16 @@ posix_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, } if (flags) { - gfid_str = uuid_utoa(stbuf.ia_gfid); - op_ret = sys_mkdir(priv->trash_path, 0755); if (errno != EEXIST && op_ret == -1) { gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_MKDIR_FAILED, "mkdir of %s failed", priv->trash_path); } else { + gfid_str = uuid_utoa(stbuf.ia_gfid); (void)snprintf(tmp_path, sizeof(tmp_path), "%s/%s", priv->trash_path, gfid_str); gf_msg_debug(this->name, 0, "Moving %s to %s", real_path, tmp_path); op_ret = sys_rename(real_path, tmp_path); - pthread_cond_signal(&priv->janitor_cond); } } else { op_ret = sys_rmdir(real_path); @@ -1442,6 +1559,9 @@ posix_symlink(call_frame_t *frame, xlator_t *this, const char *linkname, char *pgfid_xattr_key = NULL; int32_t nlink_samepgfid = 0; gf_boolean_t entry_created = _gf_false, gfid_set = _gf_false; + uuid_t uuid_req = { + 0, + }; DECLARE_OLD_FS_ID_VAR; @@ -1452,7 +1572,8 @@ posix_symlink(call_frame_t *frame, xlator_t *this, const char *linkname, priv = this->private; VALIDATE_OR_GOTO(priv, out); - GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, out); + GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, + uuid_req, out); DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); MAKE_ENTRY_HANDLE(real_path, par_path, this, loc, &stbuf); @@ -1520,7 +1641,7 @@ posix_symlink(call_frame_t *frame, xlator_t *this, const char *linkname, } ignore: - op_ret = posix_entry_create_xattr_set(this, real_path, xdata); + op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata); if (op_ret) { gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, "setting xattrs on %s failed ", real_path); @@ -1625,7 +1746,6 @@ posix_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, priv = this->private; VALIDATE_OR_GOTO(priv, out); - DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); SET_FS_ID(frame->root->uid, frame->root->gid); MAKE_ENTRY_HANDLE(real_oldpath, par_oldpath, this, oldloc, NULL); @@ -2061,6 +2181,11 @@ posix_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, char *pgfid_xattr_key = NULL; gf_boolean_t entry_created = _gf_false, gfid_set = _gf_false; mode_t mode_bit = 0; + uuid_t uuid_req = { + 0, + }; + + dict_t *xdata_rsp = dict_ref(xdata); DECLARE_OLD_FS_ID_VAR; @@ -2072,7 +2197,8 @@ posix_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, priv = this->private; VALIDATE_OR_GOTO(priv, out); - GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, out); + GFID_NULL_CHECK_AND_GOTO(frame, this, loc, xdata, op_ret, op_errno, + uuid_req, out); DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); MAKE_ENTRY_HANDLE(real_path, par_path, this, loc, &stbuf); @@ -2110,6 +2236,28 @@ posix_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, was_present = 0; } + if (!was_present) { + if (posix_is_layout_stale(xdata, par_path, this)) { + op_ret = -1; + op_errno = EIO; + if (!xdata_rsp) { + xdata_rsp = dict_new(); + if (!xdata_rsp) { + op_errno = ENOMEM; + goto out; + } + } + + if (dict_set_int32_sizen(xdata_rsp, GF_PREOP_CHECK_FAILED, 1) == + -1) { + gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_DICT_SET_FAILED, + "setting key %s in dict failed", GF_PREOP_CHECK_FAILED); + } + + goto out; + } + } + if (priv->o_direct) _flags |= O_DIRECT; @@ -2158,7 +2306,7 @@ posix_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, posix_set_gfid2path_xattr(this, real_path, loc->pargfid, loc->name); } ignore: - op_ret = posix_entry_create_xattr_set(this, real_path, xdata); + op_ret = posix_entry_create_xattr_set(this, loc, real_path, xdata); if (op_ret) { gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, "setting xattrs on %s failed ", real_path); @@ -2211,12 +2359,6 @@ fill_stat: gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_FD_PATH_SETTING_FAILED, "failed to set the fd context path=%s fd=%p", real_path, fd); - LOCK(&priv->lock); - { - priv->nr_files++; - } - UNLOCK(&priv->lock); - op_ret = 0; out: @@ -2235,7 +2377,10 @@ out: STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, (loc) ? loc->inode : NULL, &stbuf, &preparent, - &postparent, xdata); + &postparent, xdata_rsp); + + if (xdata_rsp) + dict_unref(xdata_rsp); return 0; } |
