Patch "ceph: choose readdir frag based on previous readdir reply" has been added to the 4.11-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ceph: choose readdir frag based on previous readdir reply
to the 4.11-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ceph-choose-readdir-frag-based-on-previous-readdir-reply.patch
and it can be found in the queue-4.11 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
b50c2de51e611da90cf3cf04c058f7e9bbe79e93Mon Sep 17 00:00:00 2001
From: "Yan, Zheng" <[email protected]>
Date: Mon, 24 Apr 2017 11:56:50 +0800
Subject: ceph: choose readdir frag based on previous readdir reply
From: Yan, Zheng <[email protected]>
commit b50c2de51e611da90cf3cf04c058f7e9bbe79e93 upstream.
The dirfragtree is lazily updated, it's not always accurate. Infinite loops happens in following circumstance.
- client send request to read frag A
- frag A has been fragmented into frag B and C. So mds fills the reply with contents of frag B
- client wants to read next frag C. ceph_choose_frag(frag value of C) return frag A.
The fix is using previous readdir reply to calculate next readdir frag when possible.
--- fs/ceph/dir.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
fs/ceph/dir.c +12 -7
@@ -294,7 +294,7 @@ static int ceph_readdir(struct file *filstruct ceph_mds_client *mdsc = fsc->mdsc;int i;int err; -u32 ftype; +unsigned frag =-1 ;struct ceph_mds_reply_info_parsed *rinfo;dout ("readdir %p file %p pos %llx\n" , inode, file, ctx->pos);
@@ -341,7 +341,6 @@ more:/* do we have the correct frag content buffered? */ if (need_send_readdir (fi, ctx->pos)) {struct ceph_mds_request *req; -unsigned frag;int op =ceph_snap (inode) ==CEPH_SNAPDIR ?CEPH_MDS_OP_LSSNAP :CEPH_MDS_OP_READDIR ;
@@ -352,8 +351,11 @@ more: }if (is_hash_order (ctx->pos)) { - frag =ceph_choose_frag (ci,fpos_hash (ctx->pos), -NULL ,NULL ); +/* fragtree isn't always accurate. choose frag +* based on previous reply when possible. */ +if (frag == (unsigned )-1 ) + frag =ceph_choose_frag (ci,fpos_hash (ctx->pos), +NULL ,NULL ); }else { frag =fpos_frag (ctx->pos); }
@@ -476,6 +478,7 @@ more:struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;struct ceph_vino vino;ino_t ino; +u32 ftype;BUG_ON (rde->offset < ctx->pos);
@@ -498,15 +501,17 @@ more: ctx->pos++; } +ceph_mdsc_put_request (fi->last_readdir); + fi->last_readdir =NULL ; +if (fi->next_offset >2 ) { -ceph_mdsc_put_request (fi->last_readdir); - fi->last_readdir =NULL ; + frag = fi->frag; goto more; }/* more frags? */ if (!ceph_frag_is_rightmost (fi->frag)) { -unsigned frag =ceph_frag_next (fi->frag); + frag =ceph_frag_next (fi->frag);if (is_hash_order (ctx->pos)) {loff_t new_pos =ceph_make_fpos (ceph_frag_value (frag), fi->next_offset, true);
Patches currently in stable-queue which might be from [email protected] are
queue-4.11/ceph-choose-readdir-frag-based-on-previous-readdir-reply.patch