On Mon, Apr 15, 2019 at 9:45 AM Jeff Layton <jlayton@xxxxxxxxxx> wrote: > > Ben reported tripping the BUG_ON in create_request_message during some > performance testing. Analysis of the vmcore showed that the length of > the r_dentry->d_name string changed after we allocated the buffer, but > before we encoded it. > > build_dentry_path returns pointers to d_name in the common case of > non-snapped dentries, but this optimization isn't safe. Instead, make a > copy of the string in this case. That is less efficient, but safe. > > Reported-by: Ben England <bengland@xxxxxxxxxx> > Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> > --- > fs/ceph/mds_client.c | 40 ++++++++++++++++++++++++++++++++-------- > 1 file changed, 32 insertions(+), 8 deletions(-) > > diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c > index e09feadd2ae1..4cfefe118128 100644 > --- a/fs/ceph/mds_client.c > +++ b/fs/ceph/mds_client.c > @@ -2159,9 +2159,35 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, > return path; > } > > +/* Duplicate the dentry->d_name.name safely */ > +static int clone_dentry_name(struct dentry *dentry, const char **ppath, > + int *ppathlen) > +{ > + u32 len; > + char *name; > +retry: > + len = READ_ONCE(dentry->d_name.len); > + name = kmalloc(len + 1, GFP_NOFS); > + if (!name) > + return -ENOMEM; > + > + spin_lock(&dentry->d_lock); > + if (dentry->d_name.len != len) { > + spin_unlock(&dentry->d_lock); > + kfree(name); > + goto retry; > + } > + memcpy(name, dentry->d_name.name, len); > + spin_unlock(&dentry->d_lock); > + > + name[len] = '\0'; > + *ppath = name; > + *ppathlen = len; > + return 0; > +} I would think passing a char array of PATH_MAX would be preferable to a heap allocation. Is that not typical? -- Patrick Donnelly