From a5c829a3aa1d2f66dc85350bd4c163ef12507d44 Mon Sep 17 00:00:00 2001 From: Raghavendra G Date: Sun, 23 Aug 2009 22:37:10 +0000 Subject: storage/posix: handle dentries from different mount points in readdir - If posix translator is configured to have export directories to span accross different mount points, inode number is transformed in the dentry returned. Otherwise, the entry is not added to list of entries returned in readdir callback. - storage/posix returns ENOENT if the file is on different mount point other than that of exported directory and is not configured for export directory spanning across multiple mountpoints during lookup. But, since stat-prefetch shortcuts lookup calls, its necessary that readdir return only valid dentries. Signed-off-by: Anand V. Avati BUG: 221 (stat prefetch implementation) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=221 --- xlators/storage/posix/src/posix.c | 85 +++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index b124d136201..4eb484bc062 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -3502,26 +3502,25 @@ int32_t posix_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off) { - uint64_t tmp_pfd = 0; - struct posix_fd * pfd = NULL; - DIR * dir = NULL; - int ret = -1; - size_t filled = 0; - int count = 0; - - int32_t op_ret = -1; - int32_t op_errno = 0; - - gf_dirent_t * this_entry = NULL; - gf_dirent_t entries; - struct dirent * entry = NULL; - off_t in_case = -1; - int32_t this_size = -1; - - char * real_path = NULL; - int real_path_len = -1; - char * entry_path = NULL; - int entry_path_len = -1; + uint64_t tmp_pfd = 0; + struct posix_fd *pfd = NULL; + DIR *dir = NULL; + int ret = -1; + size_t filled = 0; + int count = 0; + int32_t op_ret = -1; + int32_t op_errno = 0; + gf_dirent_t *this_entry = NULL; + gf_dirent_t entries; + struct dirent *entry = NULL; + off_t in_case = -1; + int32_t this_size = -1; + char *real_path = NULL; + int real_path_len = -1; + char *entry_path = NULL; + int entry_path_len = -1; + struct posix_private *priv = NULL; + struct stat stbuf = {0, }; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); @@ -3529,6 +3528,8 @@ posix_readdir (call_frame_t *frame, xlator_t *this, INIT_LIST_HEAD (&entries.list); + priv = this->private; + ret = fd_ctx_get (fd, this, &tmp_pfd); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, @@ -3609,25 +3610,41 @@ posix_readdir (call_frame_t *frame, xlator_t *this, break; } + strcpy (entry_path + real_path_len + 1, entry->d_name); + lstat (entry_path, &stbuf); + /* Make sure we don't access another mountpoint inside export dir. + * It may cause inode number to repeat from single export point, + * which leads to severe problems.. + */ + if (!priv->span_devices) { + if (priv->st_device[0] != stbuf.st_dev) { + continue; + } + } else { + op_ret = posix_scale_st_ino (priv, &stbuf); + if (-1 == op_ret) { + continue; + } + } + + entry->d_ino = stbuf.st_ino; - this_entry = gf_dirent_for_name (entry->d_name); + this_entry = gf_dirent_for_name (entry->d_name); - if (!this_entry) { - gf_log (this->name, GF_LOG_ERROR, - "could not create gf_dirent for entry %s: (%s)", - entry->d_name, strerror (errno)); - goto out; - } - this_entry->d_off = telldir (dir); - this_entry->d_ino = entry->d_ino; + if (!this_entry) { + gf_log (this->name, GF_LOG_ERROR, + "could not create gf_dirent for entry %s: (%s)", + entry->d_name, strerror (errno)); + goto out; + } + this_entry->d_off = telldir (dir); + this_entry->d_ino = entry->d_ino; + this_entry->d_stat = stbuf; - list_add_tail (&this_entry->list, &entries.list); + list_add_tail (&this_entry->list, &entries.list); filled += this_size; - count ++; - - strcpy (entry_path + real_path_len + 1, this_entry->d_name); - lstat (entry_path, &this_entry->d_stat); + count ++; } op_ret = count; -- cgit