diff options
| -rw-r--r-- | heal/src/glfs-heal.c | 26 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 1 | ||||
| -rw-r--r-- | tests/basic/afr/self-heald.t | 4 | ||||
| -rw-r--r-- | tests/basic/pump.t | 4 | ||||
| -rw-r--r-- | tests/include.rc | 18 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heald.c | 46 | ||||
| -rw-r--r-- | xlators/features/index/src/index.c | 42 | ||||
| -rw-r--r-- | xlators/features/index/src/index.h | 1 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 26 | 
9 files changed, 137 insertions, 31 deletions
diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c index 1056ea467c4..9416316458d 100644 --- a/heal/src/glfs-heal.c +++ b/heal/src/glfs-heal.c @@ -284,7 +284,7 @@ _get_afr_ancestor (xlator_t *xl)  static int  glfsh_process_entries (xlator_t *xl, fd_t *fd, gf_dirent_t *entries, -                       off_t *offset, uint64_t *num_entries) +                       uint64_t *offset, uint64_t *num_entries)  {          gf_dirent_t      *entry = NULL;          gf_dirent_t      *tmp = NULL; @@ -359,7 +359,7 @@ out:  static int  glfsh_crawl_directory (xlator_t   *readdir_xl, fd_t *fd, loc_t *loc)  { -        off_t           offset   = 0; +        uint64_t        offset = 0;          gf_dirent_t     entries;          int             ret = 0;          gf_boolean_t    free_entries = _gf_false; @@ -472,7 +472,27 @@ glfsh_print_pending_heals (xlator_t *xl, loc_t *rootloc)                  goto out;          } -        fd = fd_anonymous (dirloc.inode); +        fd = fd_create (dirloc.inode, GF_CLIENT_PID_GLFS_HEAL); +        if (!fd) { +                printf ("fd_create failed: %s", strerror(errno)); +                goto out; +        } +        ret = syncop_opendir (xl, &dirloc, fd); +        if (ret) { +                fd_unref(fd); +#ifdef GF_LINUX_HOST_OS /* See comment in afr_shd_index_opendir() */ +                fd = fd_anonymous (dirloc.inode); +                if (!fd) { +                        printf ("fd_anonymous failed: %s", +                                strerror(errno)); +                        goto out; +                } +#else +                printf ("opendir failed: %s", strerror(errno)); +                goto out; +#endif +        } +          ret = glfsh_crawl_directory (xl, fd, &dirloc);          if (fd)                  fd_unref (fd); diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 2493ba10816..23a932b71aa 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -115,6 +115,7 @@ enum _gf_client_pid          GF_CLIENT_PID_NO_ROOT_SQUASH    = -4,          GF_CLIENT_PID_QUOTA_MOUNT       = -5,          GF_CLIENT_PID_AFR_SELF_HEALD    = -6, +        GF_CLIENT_PID_GLFS_HEAL         = -7,  };  typedef enum _gf_boolean gf_boolean_t; diff --git a/tests/basic/afr/self-heald.t b/tests/basic/afr/self-heald.t index 37e10b254c1..6937cf227d7 100644 --- a/tests/basic/afr/self-heald.t +++ b/tests/basic/afr/self-heald.t @@ -4,6 +4,7 @@  . $(dirname $0)/../../volume.rc  cleanup; +START_TIMESTAMP=`date +%s`  function disconnected_brick_count {          local vol=$1 @@ -162,4 +163,7 @@ TEST $CLI volume create $V0 $H0:$B0/${V0}{6}  TEST $CLI volume start $V0  TEST ! $CLI volume heal $V0 info +# Check for non Linux systems that we did not mess with directory offsets +TEST ! log_newer $START_TIMESTAMP "offset reused from another DIR" +  cleanup diff --git a/tests/basic/pump.t b/tests/basic/pump.t index 6e81ddde6cd..e9e54a7a9ea 100644 --- a/tests/basic/pump.t +++ b/tests/basic/pump.t @@ -4,6 +4,7 @@  . $(dirname $0)/../volume.rc  cleanup; +START_TIMESTAMP=`date +%s`  TEST glusterd  TEST pidof glusterd @@ -41,4 +42,7 @@ done  EXPECT "" echo $files +# Check for non Linux systems that we did not mess with directory offsets +TEST ! log_newer $START_TIMESTAMP "offset reused from another DIR" +  cleanup diff --git a/tests/include.rc b/tests/include.rc index 75db2d10d0e..7c31eb65402 100644 --- a/tests/include.rc +++ b/tests/include.rc @@ -783,6 +783,24 @@ function MKFS_LOOP ()    esac  } +# usage: log_newer timestamp "string" +# search in glusterfs logs for "string" logged after timestamp seconds +# since the Epoch (usually obtained by date +%s) +log_newer() +{ +        ts=$1 +        msg=$2 +        logdir=`$CLI --print-logdir` + +        IFS="[" +        for date in `grep -hr "$msg" $logdir | awk -F '[\]]' '{print $1}'` ; do +                if [ `date -d "$date" +%s` -gt $ts ] ; then +                        return 0; +                fi +        done 2>/dev/null +        return 1 +} +  function MOUNT_LOOP ()  {    if [ $# != 2 ] ; then diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c index a341015303c..29f34107481 100644 --- a/xlators/cluster/afr/src/afr-self-heald.c +++ b/xlators/cluster/afr/src/afr-self-heald.c @@ -274,6 +274,8 @@ afr_shd_index_opendir (xlator_t *this, int child)  #ifdef GF_LINUX_HOST_OS  		fd_unref (fd);  		fd = fd_anonymous (inode); +		if (!fd) +		        goto out;  #else /* GF_LINUX_HOST_OS */  		gf_log(this->name, GF_LOG_ERROR,  		       "opendir of %s for %s failed: %s", @@ -427,7 +429,7 @@ afr_shd_index_sweep (struct subvol_healer *healer)  	fd_t *fd = NULL;  	xlator_t *subvol = NULL;  	afr_private_t *priv = NULL; -	off_t offset = 0; +	uint64_t offset = 0;  	gf_dirent_t entries;  	gf_dirent_t *entry = NULL;  	uuid_t gfid; @@ -501,11 +503,12 @@ afr_shd_index_sweep (struct subvol_healer *healer)  int  afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode)  { +	loc_t loc = {0, };  	fd_t *fd = NULL;  	xlator_t *this = NULL;  	xlator_t *subvol = NULL;  	afr_private_t *priv = NULL; -	off_t offset = 0; +	uint64_t offset = 0;  	gf_dirent_t entries;  	gf_dirent_t *entry = NULL;  	int ret = 0; @@ -514,9 +517,38 @@ afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode)  	priv = this->private;  	subvol = priv->children[healer->subvol]; -	fd = fd_anonymous (inode); -	if (!fd) -		return -errno; +	uuid_copy (loc.gfid, inode->gfid); +	loc.inode = inode_ref(inode); + +	fd = fd_create (inode, GF_CLIENT_PID_AFR_SELF_HEALD); +	if (!fd) { +		gf_log(this->name, GF_LOG_ERROR, +		       "fd_create of %s failed: %s", +		       uuid_utoa (loc.gfid), strerror(errno)); +		ret = -errno; +		goto out; +	} + +	ret = syncop_opendir (subvol, &loc, fd); +	if (ret) { +#ifdef GF_LINUX_HOST_OS /* See comment in afr_shd_index_opendir() */ +		fd_unref(fd); +		fd = fd_anonymous (inode); +		if (!fd) { +			gf_log(this->name, GF_LOG_ERROR, +			       "fd_anonymous of %s failed: %s", +			       uuid_utoa (loc.gfid), strerror(errno)); +			ret = -errno; +			goto out; +		} +#else /* GF_LINUX_HOST_OS */ +		gf_log(this->name, GF_LOG_ERROR, +		       "opendir of %s failed: %s", +		       uuid_utoa (loc.gfid), strerror(errno)); +		ret = -errno; +		goto out; +#endif /* GF_LINUX_HOST_OS */ +	}  	INIT_LIST_HEAD (&entries.list); @@ -558,6 +590,8 @@ afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode)  			break;  	} +out: +	loc_wipe (&loc);  	if (fd)  		fd_unref (fd);  	return ret; @@ -947,7 +981,7 @@ afr_shd_gather_index_entries (xlator_t *this, int child, dict_t *output)  	fd_t *fd = NULL;  	xlator_t *subvol = NULL;  	afr_private_t *priv = NULL; -	off_t offset = 0; +	uint64_t offset = 0;  	gf_dirent_t entries;  	gf_dirent_t *entry = NULL;  	uuid_t gfid; diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c index 5892f741629..f7408c1308f 100644 --- a/xlators/features/index/src/index.c +++ b/xlators/features/index/src/index.c @@ -268,10 +268,11 @@ check_delete_stale_index_file (xlator_t *this, char *filename)  }  static int -index_fill_readdir (fd_t *fd, DIR *dir, off_t off, +index_fill_readdir (fd_t *fd, index_fd_ctx_t *fctx, DIR *dir, off_t off,                      size_t size, gf_dirent_t *entries)  {          off_t     in_case = -1; +        off_t     last_off = 0;          size_t    filled = 0;          int       count = 0;          char      entrybuf[sizeof(struct dirent) + 256 + 8]; @@ -286,11 +287,11 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off,          } else {                  seekdir (dir, off);  #ifndef GF_LINUX_HOST_OS -                if (telldir(dir) != off) { +                if ((u_long)telldir(dir) != off && off != fctx->dir_eof) {                          gf_log (THIS->name, GF_LOG_ERROR, -                                "seekdir(%ld) failed on dir=%p: " +                                "seekdir(0x%llx) failed on dir=%p: "  				"Invalid argument (offset reused from " -				"another DIR * structure?)", (long)off, dir); +				"another DIR * structure?)", off, dir);                          errno = EINVAL;                          count = -1;                          goto out; @@ -299,7 +300,7 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off,          }          while (filled <= size) { -                in_case = telldir (dir); +                in_case = (u_long)telldir (dir);                  if (in_case == -1) {                          gf_log (THIS->name, GF_LOG_ERROR, @@ -335,12 +336,13 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off,                  if (this_size + filled > size) {                          seekdir (dir, in_case);  #ifndef GF_LINUX_HOST_OS -                        if (telldir(dir) != in_case) { +                        if ((u_long)telldir(dir) != in_case && +                            in_case != fctx->dir_eof) {  				gf_log (THIS->name, GF_LOG_ERROR, -					"seekdir(%ld) failed on dir=%p: " +					"seekdir(0x%llx) failed on dir=%p: "  					"Invalid argument (offset reused from "  					"another DIR * structure?)", -					(long)in_case, dir); +					in_case, dir);  				errno = EINVAL;  				count = -1;  				goto out; @@ -357,7 +359,14 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off,                                  entry->d_name, strerror (errno));                          goto out;                  } -                this_entry->d_off = telldir (dir); +                /* +                 * we store the offset of next entry here, which is +                 * probably not intended, but code using syncop_readdir() +                 * (glfs-heal.c, afr-self-heald.c, pump.c) rely on it +                 * for directory read resumption. +                 */ +                last_off = (u_long)telldir(dir); +                this_entry->d_off = last_off;                  this_entry->d_ino = entry->d_ino;                  list_add_tail (&this_entry->list, &entries->list); @@ -366,9 +375,12 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off,                  count ++;          } -        if ((!readdir (dir) && (errno == 0))) +        if ((!readdir (dir) && (errno == 0))) {                  /* Indicate EOF */                  errno = ENOENT; +                /* Remember EOF offset for later detection */ +                fctx->dir_eof = last_off; +        }  out:          return count;  } @@ -581,6 +593,7 @@ __index_fd_ctx_get (fd_t *fd, xlator_t *this, index_fd_ctx_t **ctx)                  fctx = NULL;                  goto out;          } +        fctx->dir_eof = -1;          ret = __fd_ctx_set (fd, this, (uint64_t)(long)fctx);          if (ret) { @@ -950,7 +963,7 @@ index_readdir_wrapper (call_frame_t *frame, xlator_t *this,                  goto done;          } -        count = index_fill_readdir (fd, dir, off, size, &entries); +        count = index_fill_readdir (fd, fctx, dir, off, size, &entries);          /* pick ENOENT to indicate EOF */          op_errno = errno; @@ -1271,8 +1284,11 @@ index_releasedir (xlator_t *this, fd_t *fd)                  goto out;          fctx = (index_fd_ctx_t*) (long) ctx; -        if (fctx->dir) -                closedir (fctx->dir); +        if (fctx->dir) { +                ret = closedir (fctx->dir); +                if (ret) +                        gf_log (this->name, GF_LOG_ERROR, "closedir error: %s", strerror (errno)); +        }          GF_FREE (fctx);  out: diff --git a/xlators/features/index/src/index.h b/xlators/features/index/src/index.h index 661dcdbc417..206d280e519 100644 --- a/xlators/features/index/src/index.h +++ b/xlators/features/index/src/index.h @@ -34,6 +34,7 @@ typedef struct index_inode_ctx {  typedef struct index_fd_ctx {          DIR *dir; +        off_t dir_eof;  } index_fd_ctx_t;  typedef struct index_priv { diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index a3aa57a0153..638e0f59202 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -4857,6 +4857,7 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size,                      gf_dirent_t *entries, xlator_t *this, int32_t skip_dirs)  {          off_t     in_case = -1; +        off_t     last_off = 0;          size_t    filled = 0;          int             count = 0;          char      entrybuf[sizeof(struct dirent) + 256 + 8]; @@ -4892,11 +4893,11 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size,          } else {                  seekdir (dir, off);  #ifndef GF_LINUX_HOST_OS -                if (telldir(dir) != (long)off && off != pfd->dir_eof) { +                if ((u_long)telldir(dir) != off && off != pfd->dir_eof) {                          gf_log (THIS->name, GF_LOG_ERROR, -                                "seekdir(%ld) failed on dir=%p: " +                                "seekdir(0x%llx) failed on dir=%p: "                                  "Invalid argument (offset reused from " -                                "another DIR * structure?)", (long)off, dir); +                                "another DIR * structure?)", off, dir);                          errno = EINVAL;                          count = -1;                          goto out; @@ -4905,7 +4906,7 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size,          }          while (filled <= size) { -                in_case = telldir (dir); +                in_case = (u_long)telldir (dir);                  if (in_case == -1) {                          gf_log (THIS->name, GF_LOG_ERROR, @@ -4965,13 +4966,13 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size,                  if (this_size + filled > size) {                          seekdir (dir, in_case);  #ifndef GF_LINUX_HOST_OS -                        if (telldir(dir) != (long)in_case && +                        if ((u_long)telldir(dir) != in_case &&                              in_case != pfd->dir_eof) {                                  gf_log (THIS->name, GF_LOG_ERROR, -                                        "seekdir(%ld) failed on dir=%p: " +                                        "seekdir(0x%llx) failed on dir=%p: "                                          "Invalid argument (offset reused from "                                          "another DIR * structure?)", -                                        (long)in_case, dir); +                                        in_case, dir);                                  errno = EINVAL;                                  count = -1;                                  goto out; @@ -4988,7 +4989,14 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size,                                  entry->d_name, strerror (errno));                          goto out;                  } -                this_entry->d_off = telldir (dir); +                /* +                 * we store the offset of next entry here, which is +                 * probably not intended, but code using syncop_readdir() +                 * (glfs-heal.c, afr-self-heald.c, pump.c) rely on it +                 * for directory read resumption. +                 */ +                last_off = (u_long)telldir(dir); +                this_entry->d_off = last_off;                  this_entry->d_ino = entry->d_ino;                  this_entry->d_type = entry->d_type; @@ -5002,7 +5010,7 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size,                  /* Indicate EOF */                  errno = ENOENT;                  /* Remember EOF offset for later detection */ -                pfd->dir_eof = telldir (dir); +                pfd->dir_eof = (u_long)last_off;          }  out:          return count;  | 
