We are trying to access dentry name directly and pass it
down without holding @d_lock, this is racy and possibly
make us trigger assertions:
(mdc_lib.c:137:mdc_pack_name()) ASSERTION( lu_name_is_valid_2(buf, cpy_len) ) failed:
Fix the problem by allocting memory and copy name with @d_lock
held.
Change-Id: Iae0066661f42e8fca9358cbedd9cb21828779bbb
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-on: https://review.whamcloud.com/34330
Tested-by: Jenkins
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Gu Zheng <gzheng@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
{
struct ll_sb_info *sbi = ll_i2sbi(de->d_inode);
struct dentry *parent = de->d_parent;
{
struct ll_sb_info *sbi = ll_i2sbi(de->d_inode);
struct dentry *parent = de->d_parent;
- const char *name = NULL;
int len = 0;
struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
int len = 0;
struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
/* if server supports open-by-fid, or file name is invalid, don't pack
* name in open request */
/* if server supports open-by-fid, or file name is invalid, don't pack
* name in open request */
- if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID) &&
- lu_name_is_valid_2(de->d_name.name, de->d_name.len)) {
- name = de->d_name.name;
+ if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID)) {
+retry:
+ name = kmalloc(len, GFP_NOFS);
+ if (!name)
+ RETURN(-ENOMEM);
+ /* race here */
+ spin_lock(&de->d_lock);
+ if (len != de->d_name.len) {
+ spin_unlock(&de->d_lock);
+ kfree(name);
+ goto retry;
+ }
+ memcpy(name, de->d_name.name, len);
+ spin_unlock(&de->d_lock);
+
+ if (!lu_name_is_valid_2(name, len)) {
+ kfree(name);
+ name = NULL;
+ len = 0;
+ }
}
op_data = ll_prep_md_op_data(NULL, parent->d_inode, de->d_inode,
name, len, 0, LUSTRE_OPC_ANY, NULL);
}
op_data = ll_prep_md_op_data(NULL, parent->d_inode, de->d_inode,
name, len, 0, LUSTRE_OPC_ANY, NULL);
+ if (IS_ERR(op_data)) {
+ kfree(name);
RETURN(PTR_ERR(op_data));
RETURN(PTR_ERR(op_data));
op_data->op_data = lmm;
op_data->op_data_size = lmmsize;
rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req,
&ll_md_blocking_ast, 0);
op_data->op_data = lmm;
op_data->op_data_size = lmmsize;
rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req,
&ll_md_blocking_ast, 0);
ll_finish_md_op_data(op_data);
if (rc == -ESTALE) {
/* reason for keep own exit path - don`t flood log
ll_finish_md_op_data(op_data);
if (rc == -ESTALE) {
/* reason for keep own exit path - don`t flood log