Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3da76276 authored by Andrew Perepechko's avatar Andrew Perepechko Committed by Greg Kroah-Hartman
Browse files

staging/lustre: avoid clearing i_nlink for inodes in use



The patch removes find_cbdata callbacks and clear_nlink
from dentry_iput path, since this piece of code makes
a few races possible.

The test case reproduces one of the possible races
described in LU-7925:

1) two hard links are created for the same file
2) the test calls stat(2) for link #1
3) in the middle of 2) the test opens and closes link #2
4) in the middle of 2) the test drops the ldlm locks and
   forces dentry reclaim via vm.drop_caches=2
5) in the middle of 2) ll_d_iput() clears i_nlink for
   the inode
6) the initial stat(2) continues and copies the wrong
   i_nlink value into st_nlink

Signed-off-by: default avatarAndrew Perepechko <andrew.perepechko@seagate.com>
Seagate-bug-id: MRP-3271
Reviewed-on: http://review.whamcloud.com/19164
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7925


Reviewed-by: default avatarWally Wang <wang@cray.com>
Reviewed-by: default avatarLai Siyao <lai.siyao@intel.com>
Signed-off-by: default avatarOleg Drokin <green@linuxhacker.ru>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 37199135
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -896,8 +896,6 @@ struct obd_ops {
			struct niobuf_remote *remote, int pages,
			struct niobuf_local *local,
			struct obd_trans_info *oti, int rc);
	int (*find_cbdata)(struct obd_export *, struct lov_stripe_md *,
			   ldlm_iterator_t it, void *data);
	int (*init_export)(struct obd_export *exp);
	int (*destroy_export)(struct obd_export *exp);

@@ -958,8 +956,6 @@ struct cl_attr;
struct md_ops {
	int (*getstatus)(struct obd_export *, struct lu_fid *);
	int (*null_inode)(struct obd_export *, const struct lu_fid *);
	int (*find_cbdata)(struct obd_export *, const struct lu_fid *,
			   ldlm_iterator_t, void *);
	int (*close)(struct obd_export *, struct md_op_data *,
		     struct md_open_data *, struct ptlrpc_request **);
	int (*create)(struct obd_export *, struct md_op_data *,
+0 −25
Original line number Diff line number Diff line
@@ -1177,19 +1177,6 @@ static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp,
	return rc;
}

static inline int obd_find_cbdata(struct obd_export *exp,
				  struct lov_stripe_md *lsm,
				  ldlm_iterator_t it, void *data)
{
	int rc;

	EXP_CHECK_DT_OP(exp, find_cbdata);
	EXP_COUNTER_INCREMENT(exp, find_cbdata);

	rc = OBP(exp->exp_obd, find_cbdata)(exp, lsm, it, data);
	return rc;
}

static inline void obd_import_event(struct obd_device *obd,
				    struct obd_import *imp,
				    enum obd_import_event event)
@@ -1358,18 +1345,6 @@ static inline int md_null_inode(struct obd_export *exp,
	return rc;
}

static inline int md_find_cbdata(struct obd_export *exp,
				 const struct lu_fid *fid,
				 ldlm_iterator_t it, void *data)
{
	int rc;

	EXP_CHECK_MD_OP(exp, find_cbdata);
	EXP_MD_COUNTER_INCREMENT(exp, find_cbdata);
	rc = MDP(exp->exp_obd, find_cbdata)(exp, fid, it, data);
	return rc;
}

static inline int md_close(struct obd_export *exp, struct md_op_data *op_data,
			   struct md_open_data *mod,
			   struct ptlrpc_request **request)
+1 −0
Original line number Diff line number Diff line
@@ -458,6 +458,7 @@ extern char obd_jobid_var[];
#define OBD_FAIL_LOV_INIT			    0x1403
#define OBD_FAIL_GLIMPSE_DELAY			    0x1404
#define OBD_FAIL_LLITE_XATTR_ENOMEM		    0x1405
#define OBD_FAIL_GETATTR_DELAY			    0x1409

#define OBD_FAIL_FID_INDIR	0x1501
#define OBD_FAIL_FID_INLMA	0x1502
+0 −55
Original line number Diff line number Diff line
@@ -102,39 +102,6 @@ static int ll_dcompare(const struct dentry *dentry,
	return 0;
}

static inline int return_if_equal(struct ldlm_lock *lock, void *data)
{
	return (ldlm_is_canceling(lock) && ldlm_is_discard_data(lock)) ?
		LDLM_ITER_CONTINUE : LDLM_ITER_STOP;
}

/* find any ldlm lock of the inode in mdc and lov
 * return 0    not find
 *	1    find one
 *      < 0    error
 */
static int find_cbdata(struct inode *inode)
{
	struct ll_sb_info *sbi = ll_i2sbi(inode);
	struct lov_stripe_md *lsm;
	int rc = 0;

	LASSERT(inode);
	rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode),
			    return_if_equal, NULL);
	if (rc != 0)
		return rc;

	lsm = ccc_inode_lsm_get(inode);
	if (!lsm)
		return rc;

	rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL);
	ccc_inode_lsm_put(inode, lsm);

	return rc;
}

/**
 * Called when last reference to a dentry is dropped and dcache wants to know
 * whether or not it should cache it:
@@ -155,19 +122,6 @@ static int ll_ddelete(const struct dentry *de)
	/* kernel >= 2.6.38 last refcount is decreased after this function. */
	LASSERT(d_count(de) == 1);

	/* Disable this piece of code temporarily because this is called
	 * inside dcache_lock so it's not appropriate to do lots of work
	 * here. ATTENTION: Before this piece of code enabling, LU-2487 must be
	 * resolved.
	 */
#if 0
	/* if not ldlm lock for this inode, set i_nlink to 0 so that
	 * this inode can be recycled later b=20433
	 */
	if (d_really_is_positive(de) && !find_cbdata(d_inode(de)))
		clear_nlink(d_inode(de));
#endif

	if (d_lustre_invalid((struct dentry *)de))
		return 1;
	return 0;
@@ -347,18 +301,9 @@ static int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
	return ll_revalidate_dentry(dentry, flags);
}

static void ll_d_iput(struct dentry *de, struct inode *inode)
{
	LASSERT(inode);
	if (!find_cbdata(inode))
		clear_nlink(inode);
	iput(inode);
}

const struct dentry_operations ll_d_ops = {
	.d_revalidate = ll_revalidate_nd,
	.d_release = ll_release,
	.d_delete  = ll_ddelete,
	.d_iput    = ll_d_iput,
	.d_compare = ll_dcompare,
};
+2 −0
Original line number Diff line number Diff line
@@ -3191,6 +3191,8 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
	if (res)
		return res;

	OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30);

	stat->dev = inode->i_sb->s_dev;
	if (ll_need_32bit_api(sbi))
		stat->ino = cl_fid_build_ino(&lli->lli_fid, 1);
Loading