aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-09-17 21:44:13 -0400
committerSage Weil <sage@inktank.com>2013-09-30 17:49:53 -0400
commit81c6aea5275eae453719d7f3924da07e668265c5 (patch)
tree97fab33034d7b3f99cf4e875c1ed5c50bff54b78 /fs/ceph
parent53e879a485f9def0e55c404dbc7187470a01602d (diff)
ceph: handle frag mismatch between readdir request and reply
If client has outdated directory fragments information, it may request readdir an non-existent directory fragment. In this case, the MDS finds an approximate directory fragment and sends its contents back to the client. When receiving a reply with fragment that is different than the requested one, the client need to reset the 'readdir offset'. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/dir.c11
-rw-r--r--fs/ceph/inode.c16
-rw-r--r--fs/ceph/mds_client.c3
3 files changed, 25 insertions, 5 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 868b61d56cac..2a0bcaeb189a 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -352,8 +352,18 @@ more:
352 } 352 }
353 353
354 /* note next offset and last dentry name */ 354 /* note next offset and last dentry name */
355 rinfo = &req->r_reply_info;
356 if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
357 frag = le32_to_cpu(rinfo->dir_dir->frag);
358 if (ceph_frag_is_leftmost(frag))
359 fi->next_offset = 2;
360 else
361 fi->next_offset = 0;
362 off = fi->next_offset;
363 }
355 fi->offset = fi->next_offset; 364 fi->offset = fi->next_offset;
356 fi->last_readdir = req; 365 fi->last_readdir = req;
366 fi->frag = frag;
357 367
358 if (req->r_reply_info.dir_end) { 368 if (req->r_reply_info.dir_end) {
359 kfree(fi->last_name); 369 kfree(fi->last_name);
@@ -363,7 +373,6 @@ more:
363 else 373 else
364 fi->next_offset = 0; 374 fi->next_offset = 0;
365 } else { 375 } else {
366 rinfo = &req->r_reply_info;
367 err = note_last_dentry(fi, 376 err = note_last_dentry(fi,
368 rinfo->dir_dname[rinfo->dir_nr-1], 377 rinfo->dir_dname[rinfo->dir_nr-1],
369 rinfo->dir_dname_len[rinfo->dir_nr-1]); 378 rinfo->dir_dname_len[rinfo->dir_nr-1]);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 1c9fea0c9834..9a8e396aed89 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1275,8 +1275,20 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
1275 int err = 0, i; 1275 int err = 0, i;
1276 struct inode *snapdir = NULL; 1276 struct inode *snapdir = NULL;
1277 struct ceph_mds_request_head *rhead = req->r_request->front.iov_base; 1277 struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
1278 u64 frag = le32_to_cpu(rhead->args.readdir.frag);
1279 struct ceph_dentry_info *di; 1278 struct ceph_dentry_info *di;
1279 u64 r_readdir_offset = req->r_readdir_offset;
1280 u32 frag = le32_to_cpu(rhead->args.readdir.frag);
1281
1282 if (rinfo->dir_dir &&
1283 le32_to_cpu(rinfo->dir_dir->frag) != frag) {
1284 dout("readdir_prepopulate got new frag %x -> %x\n",
1285 frag, le32_to_cpu(rinfo->dir_dir->frag));
1286 frag = le32_to_cpu(rinfo->dir_dir->frag);
1287 if (ceph_frag_is_leftmost(frag))
1288 r_readdir_offset = 2;
1289 else
1290 r_readdir_offset = 0;
1291 }
1280 1292
1281 if (req->r_aborted) 1293 if (req->r_aborted)
1282 return readdir_prepopulate_inodes_only(req, session); 1294 return readdir_prepopulate_inodes_only(req, session);
@@ -1340,7 +1352,7 @@ retry_lookup:
1340 } 1352 }
1341 1353
1342 di = dn->d_fsdata; 1354 di = dn->d_fsdata;
1343 di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset); 1355 di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
1344 1356
1345 /* inode */ 1357 /* inode */
1346 if (dn->d_inode) { 1358 if (dn->d_inode) {
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b7bda5d9611d..f51ab2627b41 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2238,8 +2238,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
2238 err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session); 2238 err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
2239 if (err == 0) { 2239 if (err == 0) {
2240 if (result == 0 && (req->r_op == CEPH_MDS_OP_READDIR || 2240 if (result == 0 && (req->r_op == CEPH_MDS_OP_READDIR ||
2241 req->r_op == CEPH_MDS_OP_LSSNAP) && 2241 req->r_op == CEPH_MDS_OP_LSSNAP))
2242 rinfo->dir_nr)
2243 ceph_readdir_prepopulate(req, req->r_session); 2242 ceph_readdir_prepopulate(req, req->r_session);
2244 ceph_unreserve_caps(mdsc, &req->r_caps_reservation); 2243 ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
2245 } 2244 }