diff options
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r-- | fs/ceph/dir.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 766410a12c2c..c29d6ae68874 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -141,7 +141,7 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx, | |||
141 | 141 | ||
142 | /* start at beginning? */ | 142 | /* start at beginning? */ |
143 | if (ctx->pos == 2 || last == NULL || | 143 | if (ctx->pos == 2 || last == NULL || |
144 | ctx->pos < ceph_dentry(last)->offset) { | 144 | fpos_cmp(ctx->pos, ceph_dentry(last)->offset) < 0) { |
145 | if (list_empty(&parent->d_subdirs)) | 145 | if (list_empty(&parent->d_subdirs)) |
146 | goto out_unlock; | 146 | goto out_unlock; |
147 | p = parent->d_subdirs.prev; | 147 | p = parent->d_subdirs.prev; |
@@ -182,9 +182,16 @@ more: | |||
182 | spin_unlock(&dentry->d_lock); | 182 | spin_unlock(&dentry->d_lock); |
183 | spin_unlock(&parent->d_lock); | 183 | spin_unlock(&parent->d_lock); |
184 | 184 | ||
185 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ | ||
186 | if (!ceph_dir_is_complete(dir)) { | ||
187 | dout(" lost dir complete on %p; falling back to mds\n", dir); | ||
188 | dput(dentry); | ||
189 | err = -EAGAIN; | ||
190 | goto out; | ||
191 | } | ||
192 | |||
185 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos, | 193 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos, |
186 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 194 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
187 | ctx->pos = di->offset; | ||
188 | if (!dir_emit(ctx, dentry->d_name.name, | 195 | if (!dir_emit(ctx, dentry->d_name.name, |
189 | dentry->d_name.len, | 196 | dentry->d_name.len, |
190 | ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), | 197 | ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), |
@@ -198,19 +205,12 @@ more: | |||
198 | return 0; | 205 | return 0; |
199 | } | 206 | } |
200 | 207 | ||
208 | ctx->pos = di->offset + 1; | ||
209 | |||
201 | if (last) | 210 | if (last) |
202 | dput(last); | 211 | dput(last); |
203 | last = dentry; | 212 | last = dentry; |
204 | 213 | ||
205 | ctx->pos++; | ||
206 | |||
207 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ | ||
208 | if (!ceph_dir_is_complete(dir)) { | ||
209 | dout(" lost dir complete on %p; falling back to mds\n", dir); | ||
210 | err = -EAGAIN; | ||
211 | goto out; | ||
212 | } | ||
213 | |||
214 | spin_lock(&parent->d_lock); | 214 | spin_lock(&parent->d_lock); |
215 | p = p->prev; /* advance to next dentry */ | 215 | p = p->prev; /* advance to next dentry */ |
216 | goto more; | 216 | goto more; |
@@ -296,6 +296,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) | |||
296 | err = __dcache_readdir(file, ctx, shared_gen); | 296 | err = __dcache_readdir(file, ctx, shared_gen); |
297 | if (err != -EAGAIN) | 297 | if (err != -EAGAIN) |
298 | return err; | 298 | return err; |
299 | frag = fpos_frag(ctx->pos); | ||
300 | off = fpos_off(ctx->pos); | ||
299 | } else { | 301 | } else { |
300 | spin_unlock(&ci->i_ceph_lock); | 302 | spin_unlock(&ci->i_ceph_lock); |
301 | } | 303 | } |
@@ -446,7 +448,6 @@ more: | |||
446 | if (atomic_read(&ci->i_release_count) == fi->dir_release_count) { | 448 | if (atomic_read(&ci->i_release_count) == fi->dir_release_count) { |
447 | dout(" marking %p complete\n", inode); | 449 | dout(" marking %p complete\n", inode); |
448 | __ceph_dir_set_complete(ci, fi->dir_release_count); | 450 | __ceph_dir_set_complete(ci, fi->dir_release_count); |
449 | ci->i_max_offset = ctx->pos; | ||
450 | } | 451 | } |
451 | spin_unlock(&ci->i_ceph_lock); | 452 | spin_unlock(&ci->i_ceph_lock); |
452 | 453 | ||
@@ -935,14 +936,16 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
935 | * to do it here. | 936 | * to do it here. |
936 | */ | 937 | */ |
937 | 938 | ||
938 | /* d_move screws up d_subdirs order */ | ||
939 | ceph_dir_clear_complete(new_dir); | ||
940 | |||
941 | d_move(old_dentry, new_dentry); | 939 | d_move(old_dentry, new_dentry); |
942 | 940 | ||
943 | /* ensure target dentry is invalidated, despite | 941 | /* ensure target dentry is invalidated, despite |
944 | rehashing bug in vfs_rename_dir */ | 942 | rehashing bug in vfs_rename_dir */ |
945 | ceph_invalidate_dentry_lease(new_dentry); | 943 | ceph_invalidate_dentry_lease(new_dentry); |
944 | |||
945 | /* d_move screws up sibling dentries' offsets */ | ||
946 | ceph_dir_clear_complete(old_dir); | ||
947 | ceph_dir_clear_complete(new_dir); | ||
948 | |||
946 | } | 949 | } |
947 | ceph_mdsc_put_request(req); | 950 | ceph_mdsc_put_request(req); |
948 | return err; | 951 | return err; |