summaryrefslogtreecommitdiffstats
path: root/xlators/performance/readdir-ahead/src/readdir-ahead.h
diff options
context:
space:
mode:
authorKrutika Dhananjay <kdhananj@redhat.com>2017-01-17 16:40:04 +0530
committerRaghavendra G <rgowdapp@redhat.com>2018-08-18 07:28:53 +0000
commitc9bde3021202f1d5c5a2d19ac05a510fc1f788ac (patch)
treeeba54e5f791b33d079afae9655d5438d007c3091 /xlators/performance/readdir-ahead/src/readdir-ahead.h
parent045d70a5450daa85aa5564b6e9f93065c342ab12 (diff)
performance/readdir-ahead: keep stats of cached dentries in sync with modifications
PROBLEM: Stats of dentries that are readdirp'd ahead can become stale due to fops like writes, truncate etc that modify the file pointed by dentries. When a readdir is finally wound at offset corresponding to these entries, the iatts that are returned to the application come from readdir-ahead's cache, which are stale by now. This problem gets further aggravated when caching translators/modules cache and continue to serve this stale information. FIX: * Store the iatt in context of the inode pointed by dentry. * Whenever the inode pointed by dentry undergoes modification, in cbk of modification fop, update the iatt stored in inode-ctx to reflect the modification. * When serving a readdirp response from application, update iatts of dentries with the iatts stored in the context of inodes pointed by these dentries. * Some fops don't have valid iatts in their responses. For eg., write response whose data is still cached in write-behind will have zeroed out stat. In this case keep only ia_type and ia_gfid and reset rest of the iatt members to zero. - fuse-bridge in this case just sends "entry" information back to kernel and attr is not sent. - gfapi sets entry->inode to NULL and zeroes out the entire stat * There is one tiny race between the entry creation and a readdirp on its parent dir, which could cause the inode-ctx setting and inode ctx reading to happen on two different inode objects. To prevent this, when entry->inode doesn't eqaul to linked_inode, - fuse-bridge is made to send only "entry" information without attributes - gfapi sets entry->inode to NULL and zeroes out the entire stat. Change-Id: Ia27ff49a61922e88c73a1547ad8aacc9968a69df BUG: 1390050 Updates: bz#1390050 Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com> Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'xlators/performance/readdir-ahead/src/readdir-ahead.h')
-rw-r--r--xlators/performance/readdir-ahead/src/readdir-ahead.h52
1 files changed, 49 insertions, 3 deletions
diff --git a/xlators/performance/readdir-ahead/src/readdir-ahead.h b/xlators/performance/readdir-ahead/src/readdir-ahead.h
index 3c06cc0f107..7dbed4c60ed 100644
--- a/xlators/performance/readdir-ahead/src/readdir-ahead.h
+++ b/xlators/performance/readdir-ahead/src/readdir-ahead.h
@@ -19,6 +19,44 @@
#define RDA_FD_BYPASS (1 << 4)
#define RDA_FD_PLUGGED (1 << 5)
+
+#define RDA_COMMON_MODIFICATION_FOP(name, frame, this, __inode, __xdata, args ...)\
+ do { \
+ struct rda_local *__local = NULL; \
+ rda_inode_ctx_t *ctx_p = NULL; \
+ \
+ __local = mem_get0 (this->local_pool); \
+ __local->inode = inode_ref (__inode); \
+ LOCK (&__inode->lock); \
+ { \
+ ctx_p = __rda_inode_ctx_get (__inode, this); \
+ } \
+ UNLOCK (&__inode->lock); \
+ __local->generation = GF_ATOMIC_GET (ctx_p->generation); \
+ \
+ frame->local = __local; \
+ if (__xdata) \
+ __local->xattrs = dict_ref (__xdata); \
+ \
+ STACK_WIND (frame, rda_##name##_cbk, FIRST_CHILD(this), \
+ FIRST_CHILD(this)->fops->name, args, __xdata); \
+ } while (0)
+
+
+#define RDA_STACK_UNWIND(fop, frame, params ...) do { \
+ struct rda_local *__local = NULL; \
+ if (frame) { \
+ __local = frame->local; \
+ frame->local = NULL; \
+ } \
+ STACK_UNWIND_STRICT (fop, frame, params); \
+ if (__local) { \
+ rda_local_wipe (__local); \
+ mem_put (__local); \
+ } \
+} while (0)
+
+
struct rda_fd_ctx {
off_t cur_offset; /* current head of the ctx */
size_t cur_size; /* current size of the preload */
@@ -34,9 +72,12 @@ struct rda_fd_ctx {
struct rda_local {
struct rda_fd_ctx *ctx;
- fd_t *fd;
- off_t offset;
- dict_t *xattrs; /* xattrs to be sent in readdirp() */
+ fd_t *fd;
+ dict_t *xattrs; /* md-cache keys to be sent in readdirp() */
+ inode_t *inode;
+ off_t offset;
+ uint64_t generation;
+ int32_t skip_dir;
};
struct rda_priv {
@@ -48,4 +89,9 @@ struct rda_priv {
gf_boolean_t parallel_readdir;
};
+typedef struct rda_inode_ctx {
+ struct iatt statbuf;
+ gf_atomic_t generation;
+} rda_inode_ctx_t;
+
#endif /* __READDIR_AHEAD_H */