diff options
author | Raghavendra G <raghavendra@gluster.com> | 2009-08-23 22:37:10 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2009-09-08 01:43:01 -0700 |
commit | a5c829a3aa1d2f66dc85350bd4c163ef12507d44 (patch) | |
tree | 87fa7d05badb07a434a9f9b8fc4d5fc226a65b5b /xlators | |
parent | 727c933a62e6b436c0aabcf80b6cd67620ee5429 (diff) |
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 <avati@dev.gluster.com>
BUG: 221 (stat prefetch implementation)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=221
Diffstat (limited to 'xlators')
-rw-r--r-- | xlators/storage/posix/src/posix.c | 85 |
1 files changed, 51 insertions, 34 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index b124d1362..4eb484bc0 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; |