diff options
author | Amar Tumballi <amar@gluster.com> | 2011-10-13 12:59:41 +0530 |
---|---|---|
committer | Vijay Bellur <vijay@gluster.com> | 2011-10-20 00:20:29 -0700 |
commit | 429550b75d2b97f24a102cc648bf9d8240965f93 (patch) | |
tree | 9c0dade4fe8c803303d5a0afd629d280932fde27 | |
parent | 54b44736b1558cd7e3adf75a8ecfe1a5c236dc20 (diff) |
distribute: handle migration of symlink and special files
TODO: currently, wrt. rebalance/decommissioning, only pending thing
is hardlink migration.
Change-Id: I30cd06802e84c95601a5a081198f1f09c6d6bc01
BUG: 3714
Reviewed-on: http://review.gluster.com/578
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Shishir Gowda <shishirng@gluster.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
-rw-r--r-- | libglusterfs/src/syncop.c | 98 | ||||
-rw-r--r-- | libglusterfs/src/syncop.h | 5 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 2 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-common.h | 4 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-rebalance.c | 240 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rebalance.c | 2 |
6 files changed, 292 insertions, 59 deletions
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index 1380d15f36b..a9b49bb5869 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -985,3 +985,101 @@ syncop_stat (xlator_t *subvol, loc_t *loc, struct iatt *stbuf) return args.op_ret; } + +int32_t +syncop_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_symlink (xlator_t *subvol, loc_t *loc, char *newpath, dict_t *dict) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_symlink_cbk, subvol->fops->symlink, + newpath, loc, dict); + + errno = args.op_errno; + return args.op_ret; + +} + +int +syncop_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, const char *path, + struct iatt *stbuf) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if ((op_ret != -1) && path) + args->buffer = gf_strdup (path); + + __wake (args); + + return 0; +} + +int +syncop_readlink (xlator_t *subvol, loc_t *loc, char **buffer, size_t size) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_readlink_cbk, subvol->fops->readlink, + loc, size); + + if (buffer) + *buffer = args.buffer; + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_mknod (xlator_t *subvol, loc_t *loc, mode_t mode, dev_t rdev, + dict_t *dict) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_mknod_cbk, subvol->fops->mknod, + loc, mode, rdev, dict); + + errno = args.op_errno; + return args.op_ret; + +} diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index 1c3fe07b517..9d9c5a9ccf7 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -82,6 +82,7 @@ struct syncargs { struct iovec *vector; int count; struct iobref *iobref; + char *buffer; /* do not touch */ pthread_mutex_t mutex; @@ -207,5 +208,9 @@ int syncop_fsync (xlator_t *subvol, fd_t *fd); int syncop_fstat (xlator_t *subvol, fd_t *fd, struct iatt *stbuf); int syncop_stat (xlator_t *subvol, loc_t *loc, struct iatt *stbuf); +int syncop_symlink (xlator_t *subvol, loc_t *loc, char *newpath, dict_t *dict); +int syncop_readlink (xlator_t *subvol, loc_t *loc, char **buffer, size_t size); +int syncop_mknod (xlator_t *subvol, loc_t *loc, mode_t mode, dev_t rdev, + dict_t *dict); #endif /* _SYNCOP_H */ diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index 7cf5229aad1..0fa14968beb 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -1845,7 +1845,7 @@ dht_setxattr (call_frame_t *frame, xlator_t *this, tmp = dict_get (xattr, "distribute.migrate-data"); if (tmp) { - if (!IA_ISREG (loc->inode->ia_type)) { + if (IA_ISDIR (loc->inode->ia_type)) { op_errno = ENOTSUP; goto err; } diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h index a6dc0b00bd7..5d921239ef4 100644 --- a/xlators/cluster/dht/src/dht-common.h +++ b/xlators/cluster/dht/src/dht-common.h @@ -236,12 +236,12 @@ typedef struct dht_disk_layout dht_disk_layout_t; #define DHT_LINKFILE_MODE (S_ISVTX) #define check_is_linkfile(i,s,x) ( \ - ((st_mode_from_ia (s->ia_prot, s->ia_type) & ~S_IFMT) \ + ((st_mode_from_ia ((s)->ia_prot, (s)->ia_type) & ~S_IFMT) \ == DHT_LINKFILE_MODE) && \ dict_get (x, DHT_LINKFILE_KEY)) #define check_is_linkfile_wo_dict(i,s) ( \ - ((st_mode_from_ia (s->ia_prot, s->ia_type) & ~S_IFMT) \ + ((st_mode_from_ia ((s)->ia_prot, (s)->ia_type) & ~S_IFMT) \ == DHT_LINKFILE_MODE)) #define IS_DHT_MIGRATION_PHASE2(buf) ( \ diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c index 71fd7b36777..ab555720bb8 100644 --- a/xlators/cluster/dht/src/dht-rebalance.c +++ b/xlators/cluster/dht/src/dht-rebalance.c @@ -61,8 +61,13 @@ dht_write_with_holes (xlator_t *to, fd_t *fd, struct iovec *vec, int count, (start_idx - tmp_offset), (offset + tmp_offset), iobref); - if (ret < 0) + /* 'path' will be logged in calling function */ + if (ret < 0) { + gf_log (THIS->name, GF_LOG_WARNING, + "failed to write (%s)", + strerror (errno)); goto out; + } write_needed = 0; } @@ -74,8 +79,13 @@ dht_write_with_holes (xlator_t *to, fd_t *fd, struct iovec *vec, int count, ret = syncop_write (to, fd, (buf + tmp_offset), (buf_len - tmp_offset), (offset + tmp_offset), iobref); - if (ret < 0) + if (ret < 0) { + /* 'path' will be logged in calling function */ + gf_log (THIS->name, GF_LOG_WARNING, + "failed to write (%s)", + strerror (errno)); goto out; + } } size_pending = (size - buf_len); @@ -90,15 +100,13 @@ out: } static inline int -__is_file_migratable (xlator_t *this, loc_t *loc, dict_t *rsp_dict, - struct iatt *stbuf) +__is_file_migratable (xlator_t *this, loc_t *loc, struct iatt *stbuf) { int ret = -1; - if (!IA_ISREG (stbuf->ia_type)) { + if (IA_ISDIR (stbuf->ia_type)) { gf_log (this->name, GF_LOG_WARNING, - "%s: migrate-file called on non-regular entry (0%o)", - loc->path, stbuf->ia_type); + "%s: migrate-file called on directory", loc->path); ret = -1; goto out; } @@ -145,7 +153,8 @@ __dht_rebalance_create_dst_file (xlator_t *to, xlator_t *from, loc_t *loc, struc fd = fd_create (loc->inode, DHT_REBALANCE_PID); if (!fd) { gf_log (this->name, GF_LOG_ERROR, - "%s: fd create failed (destination)", loc->path); + "%s: fd create failed (destination) (%s)", + loc->path, strerror (errno)); ret = -1; goto out; } @@ -161,6 +170,13 @@ __dht_rebalance_create_dst_file (xlator_t *to, xlator_t *from, loc_t *loc, struc goto out; } } + if ((ret == -1) && (errno != ENOENT)) { + /* File exists in destination, but not accessible */ + gf_log (THIS->name, GF_LOG_WARNING, + "%s: failed to lookup file (%s)", + loc->path, strerror (errno)); + goto out; + } /* Create the destination with LINKFILE mode, and linkto xattr, if the linkfile already exists, it will just open the file */ @@ -168,7 +184,8 @@ __dht_rebalance_create_dst_file (xlator_t *to, xlator_t *from, loc_t *loc, struc dict); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, - "failed to create %s on %s", loc->path, to->name); + "failed to create %s on %s (%s)", + loc->path, to->name, strerror (errno)); goto out; } @@ -196,16 +213,16 @@ __dht_check_free_space (xlator_t *to, xlator_t *from, loc_t *loc, ret = syncop_statfs (from, loc, &src_statfs); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "failed to get statfs of %s on %s", - loc->path, from->name); + "failed to get statfs of %s on %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } ret = syncop_statfs (to, loc, &dst_statfs); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "failed to get statfs of %s on %s", - loc->path, to->name); + "failed to get statfs of %s on %s (%s)", + loc->path, to->name, strerror (errno)); goto out; } if (((dst_statfs.f_bavail * @@ -305,8 +322,8 @@ __dht_rebalance_open_src_file (xlator_t *from, xlator_t *to, loc_t *loc, ret = syncop_open (from, loc, O_RDWR, fd); if (ret == -1) { gf_log (this->name, GF_LOG_ERROR, - "failed to open file %s on %s", - loc->path, from->name); + "failed to open file %s on %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } @@ -328,8 +345,8 @@ __dht_rebalance_open_src_file (xlator_t *from, xlator_t *to, loc_t *loc, ret = syncop_setxattr (from, loc, dict, 0); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "failed to set xattr on %s in %s", - loc->path, from->name); + "failed to set xattr on %s in %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } @@ -342,8 +359,8 @@ __dht_rebalance_open_src_file (xlator_t *from, xlator_t *to, loc_t *loc, ret = syncop_setattr (from, loc, &iatt, GF_SET_ATTR_MODE, NULL, NULL); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "failed to set mode on %s in %s", - loc->path, from->name); + "failed to set mode on %s in %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } @@ -359,6 +376,113 @@ out: return ret; } +int +migrate_special_files (xlator_t *this, xlator_t *from, xlator_t *to, loc_t *loc, + struct iatt *buf) +{ + int ret = -1; + dict_t *rsp_dict = NULL; + dict_t *dict = NULL; + char *link = NULL; + struct iatt stbuf = {0,}; + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_set_int32 (dict, DHT_LINKFILE_KEY, 256); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "%s: failed to set 'linkto' key in dict", loc->path); + goto out; + } + + /* check in the destination if the file is link file */ + ret = syncop_lookup (to, loc, dict, &stbuf, &rsp_dict, NULL); + if ((ret == -1) && (errno != ENOENT)) { + gf_log (this->name, GF_LOG_WARNING, "%s: lookup failed (%s)", + loc->path, strerror (errno)); + goto out; + } + + /* we no more require this key */ + dict_del (dict, DHT_LINKFILE_KEY); + + /* file exists in target node, only if it is 'linkfile' its valid, + otherwise, error out */ + if (!ret) { + if (!check_is_linkfile (loc->inode, &stbuf, rsp_dict)) { + gf_log (this->name, GF_LOG_WARNING, + "%s: file exists in destination", loc->path); + ret = -1; + goto out; + } + + /* as file is linkfile, delete it */ + ret = syncop_unlink (to, loc); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "%s: failed to delete the linkfile (%s)", + loc->path, strerror (errno)); + goto out; + } + } + + /* Set the gfid of the source file in dict */ + ret = dict_set_static_bin (dict, "gfid-req", buf->ia_gfid, 16); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "%s: failed to set gfid in dict for create", loc->path); + goto out; + } + + /* Create the file in target */ + if (IA_ISLNK (buf->ia_type)) { + /* Handle symlinks separately */ + ret = syncop_readlink (from, loc, &link, buf->ia_size); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "%s: readlink on symlink failed (%s)", + loc->path, strerror (errno)); + goto out; + } + + ret = syncop_symlink (to, loc, link, dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "%s: creating symlink failed (%s)", + loc->path, strerror (errno)); + goto out; + } + + goto done; + } + + ret = syncop_mknod (to, loc, st_mode_from_ia (buf->ia_prot, + buf->ia_type), + makedev (ia_major (buf->ia_rdev), + ia_minor (buf->ia_rdev)), dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "%s: mknod failed (%s)", + loc->path, strerror (errno)); + goto out; + } + +done: + ret = syncop_unlink (from, loc); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "%s: unlink failed (%s)", + loc->path, strerror (errno)); + +out: + if (dict) + dict_unref (dict); + + if (rsp_dict) + dict_unref (rsp_dict); + + return ret; +} /* return values: @@ -380,7 +504,6 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, fd_t *dst_fd = NULL; dict_t *dict = NULL; dict_t *xattr = NULL; - dict_t *rsp_dict = NULL; int file_has_holes = 0; gf_log (this->name, GF_LOG_INFO, "%s: attempting to move from %s to %s", @@ -390,17 +513,11 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, if (!dict) goto out; - ret = dict_set_int32 (dict, GLUSTERFS_OPEN_FD_COUNT, 4); - if (ret) - gf_log (this->name, GF_LOG_WARNING, - "%s: failed to set fd-count key in dict, may attempt " - "migration of file which has open fds", loc->path); - /* Phase 1 - Data migration is in progress from now on */ - ret = syncop_lookup (from, loc, dict, &stbuf, &rsp_dict, NULL); + ret = syncop_lookup (from, loc, NULL, &stbuf, NULL, NULL); if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to lookup %s on %s", - loc->path, from->name); + gf_log (this->name, GF_LOG_ERROR, "%s: lookup failed on %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } @@ -408,10 +525,17 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, src_ia_prot = stbuf.ia_prot; /* Check if file can be migrated */ - ret = __is_file_migratable (this, loc, rsp_dict, &stbuf); + ret = __is_file_migratable (this, loc, &stbuf); if (ret) goto out; + /* Take care of the special files */ + if (!IA_ISREG (stbuf.ia_type)) { + /* Special files */ + ret = migrate_special_files (this, from, to, loc, &stbuf); + goto out; + } + /* create the destination, with required modes/xattr */ ret = __dht_rebalance_create_dst_file (to, from, loc, &stbuf, dict, &dst_fd); @@ -436,8 +560,8 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, ret = syncop_fstat (from, src_fd, &stbuf); if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to lookup %s on %s", - loc->path, from->name); + gf_log (this->name, GF_LOG_ERROR, "failed to lookup %s on %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } @@ -455,8 +579,8 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, ret = syncop_ftruncate (to, dst_fd, 0); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "%s: failed to reset the target size back to 0", - loc->path); + "%s: failed to reset target size back to 0 (%s)", + loc->path, strerror (errno)); } ret = -1; @@ -467,19 +591,22 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, ret = syncop_listxattr (from, loc, &xattr); if (ret == -1) gf_log (this->name, GF_LOG_WARNING, - "%s: failed to get xattr from %s", loc->path, from->name); + "%s: failed to get xattr from %s (%s)", + loc->path, from->name, strerror (errno)); ret = syncop_setxattr (to, loc, xattr, 0); if (ret == -1) gf_log (this->name, GF_LOG_WARNING, - "%s: failed to set xattr on %s", loc->path, to->name); + "%s: failed to set xattr on %s (%s)", + loc->path, to->name, strerror (errno)); /* TODO: Sync the locks */ ret = syncop_fsync (to, dst_fd); if (ret) gf_log (this->name, GF_LOG_WARNING, - "%s: failed to fsync on %s", loc->path, to->name); + "%s: failed to fsync on %s (%s)", + loc->path, to->name, strerror (errno)); /* Phase 2 - Data-Migration Complete, Housekeeping updates pending */ @@ -488,8 +615,8 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, if (ret < 0) { /* Failed to get the stat info */ gf_log (this->name, GF_LOG_ERROR, - "failed to fstat file %s on %s", - loc->path, from->name); + "failed to fstat file %s on %s (%s)", + loc->path, from->name, strerror (errno)); goto out; } @@ -510,8 +637,8 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, GF_SET_ATTR_MODE), NULL, NULL); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to perform setattr on %s", - loc->path, to->name); + "%s: failed to perform setattr on %s (%s)", + loc->path, to->name, strerror (errno)); } /* Because 'futimes' is not portable */ @@ -520,8 +647,8 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, NULL, NULL); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to perform setattr on %s", - loc->path, to->name); + "%s: failed to perform setattr on %s (%s)", + loc->path, to->name, strerror (errno)); } /* Make the source as a linkfile first before deleting it */ @@ -530,16 +657,16 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, GF_SET_ATTR_MODE, NULL, NULL); if (ret) { gf_log (this->name, GF_LOG_WARNING, \ - "%s: failed to perform setattr on %s", - loc->path, from->name); + "%s: failed to perform setattr on %s (%s)", + loc->path, from->name, strerror (errno)); } /* Do a stat and check the gfid before unlink */ ret = syncop_stat (from, loc, &empty_iatt); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to do a stat on %s", - loc->path, from->name); + "%s: failed to do a stat on %s (%s)", + loc->path, from->name, strerror (errno)); } if (uuid_compare (empty_iatt.ia_gfid, loc->inode->gfid) == 0) { @@ -547,8 +674,8 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, ret = syncop_unlink (from, loc); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to perform unlink on %s", - loc->path, from->name); + "%s: failed to perform unlink on %s (%s)", + loc->path, from->name, strerror (errno)); } } @@ -557,23 +684,23 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, ret = syncop_ftruncate (from, src_fd, 0); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to perform truncate on %s", - loc->path, from->name); + "%s: failed to perform truncate on %s (%s)", + loc->path, from->name, strerror (errno)); } /* remove the 'linkto' xattr from the destination */ ret = syncop_removexattr (to, loc, DHT_LINKFILE_KEY); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to perform removexattr on %s", - loc->path, to->name); + "%s: failed to perform removexattr on %s (%s)", + loc->path, to->name, strerror (errno)); } ret = syncop_lookup (this, loc, NULL, NULL, NULL, NULL); if (ret) { gf_log (this->name, GF_LOG_WARNING, - "%s: failed to lookup the file on subvolumes", - loc->path); + "%s: failed to lookup the file on subvolumes (%s)", + loc->path, strerror (errno)); } gf_log (this->name, GF_LOG_INFO, @@ -585,6 +712,9 @@ out: if (dict) dict_unref (dict); + if (xattr) + dict_unref (xattr); + if (dst_fd) syncop_close (dst_fd); if (src_fd) diff --git a/xlators/mgmt/glusterd/src/glusterd-rebalance.c b/xlators/mgmt/glusterd/src/glusterd-rebalance.c index 82991596315..f848d73fddf 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rebalance.c +++ b/xlators/mgmt/glusterd/src/glusterd-rebalance.c @@ -98,7 +98,7 @@ gf_glusterd_rebalance_move_data (glusterd_volinfo_t *volinfo, const char *dir) if (ret == -1) continue; - if (!S_ISREG (stbuf.st_mode)) + if (S_ISDIR (stbuf.st_mode)) continue; defrag->num_files_lookedup += 1; |