int (*coo_getstripe)(const struct lu_env *env, struct cl_object *obj,
struct lov_user_md __user *lum);
/**
- * Find whether there is any callback data (ldlm lock) attached upon
- * the object.
- */
- int (*coo_find_cbdata)(const struct lu_env *env, struct cl_object *obj,
- ldlm_iterator_t iter, void *data);
- /**
* Get FIEMAP mapping from the object.
*/
int (*coo_fiemap)(const struct lu_env *env, struct cl_object *obj,
void cl_object_kill (const struct lu_env *env, struct cl_object *obj);
int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj,
struct lov_user_md __user *lum);
-int cl_object_find_cbdata(const struct lu_env *env, struct cl_object *obj,
- ldlm_iterator_t iter, void *data);
int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj,
struct ll_fiemap_info_key *fmkey, struct fiemap *fiemap,
size_t *buflen);
int (*m_getstatus)(struct obd_export *, struct lu_fid *);
int (*m_null_inode)(struct obd_export *, const struct lu_fid *);
- int (*m_find_cbdata)(struct obd_export *, const struct lu_fid *,
- ldlm_iterator_t, void *);
-
int (*m_getattr_name)(struct obd_export *, struct md_op_data *,
struct ptlrpc_request **);
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;
- ENTRY;
- 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)
#define OBD_FAIL_MAKE_LOVEA_HOLE 0x1406
#define OBD_FAIL_LLITE_LOST_LAYOUT 0x1407
#define OBD_FAIL_LLITE_NO_CHECK_DEAD 0x1408
+#define OBD_FAIL_GETATTR_DELAY 0x1409
#define OBD_FAIL_FID_INDIR 0x1501
#define OBD_FAIL_FID_INLMA 0x1502
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 lu_env *env;
- __u16 refcheck;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int rc = 0;
- ENTRY;
-
- LASSERT(inode);
- rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode),
- return_if_equal, NULL);
- if (rc != 0)
- RETURN(rc);
-
- if (ll_i2info(inode)->lli_clob != NULL) {
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- RETURN(PTR_ERR(env));
-
- rc = cl_object_find_cbdata(env, ll_i2info(inode)->lli_clob,
- return_if_equal, NULL);
- cl_env_put(env, &refcheck);
- }
-
- RETURN(rc);
-}
-
/**
* Called when last reference to a dentry is dropped and dcache wants to know
* whether or not it should cache it:
}
#endif
-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,
};
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);
RETURN(0);
}
-static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid,
- ldlm_iterator_t it, void *data)
-{
- struct obd_device *obd = exp->exp_obd;
- struct lmv_obd *lmv = &obd->u.lmv;
- int i;
- int tgt;
- int rc;
- ENTRY;
-
- rc = lmv_check_connect(obd);
- if (rc)
- RETURN(rc);
-
- CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid));
-
- /*
- * With DNE every object can have two locks in different namespaces:
- * lookup lock in space of MDT storing direntry and update/open lock in
- * space of MDT storing inode. Try the MDT that the FID maps to first,
- * since this can be easily found, and only try others if that fails.
- */
- for (i = 0, tgt = lmv_find_target_index(lmv, fid);
- i < lmv->desc.ld_tgt_count;
- i++, tgt = (tgt + 1) % lmv->desc.ld_tgt_count) {
- if (tgt < 0) {
- CDEBUG(D_HA, "%s: "DFID" is inaccessible: rc = %d\n",
- obd->obd_name, PFID(fid), tgt);
- tgt = 0;
- }
-
- if (lmv->tgts[tgt] == NULL ||
- lmv->tgts[tgt]->ltd_exp == NULL)
- continue;
-
- rc = md_find_cbdata(lmv->tgts[tgt]->ltd_exp, fid, it, data);
- if (rc)
- RETURN(rc);
- }
-
- RETURN(rc);
-}
-
-
static int lmv_close(struct obd_export *exp, struct md_op_data *op_data,
struct md_open_data *mod, struct ptlrpc_request **request)
{
struct md_ops lmv_md_ops = {
.m_getstatus = lmv_getstatus,
.m_null_inode = lmv_null_inode,
- .m_find_cbdata = lmv_find_cbdata,
.m_close = lmv_close,
.m_create = lmv_create,
.m_enqueue = lmv_enqueue,
struct cl_object *obj, struct cl_io *io);
int (*llo_getattr)(const struct lu_env *env, struct cl_object *obj,
struct cl_attr *attr);
- int (*llo_find_cbdata)(const struct lu_env *env, struct cl_object *obj,
- ldlm_iterator_t iter, void *data);
};
static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov);
RETURN(result);
}
-static int lov_find_cbdata_empty(const struct lu_env *env,
- struct cl_object *obj, ldlm_iterator_t iter,
- void *data)
-{
- return 0;
-}
-
-static int lov_find_cbdata_raid0(const struct lu_env *env,
- struct cl_object *obj, ldlm_iterator_t iter,
- void *data)
-{
- struct lov_object *lov = cl2lov(obj);
- struct lov_layout_raid0 *r0 = lov_r0(lov);
- struct cl_object *subobj;
- int i;
- int rc = 0;
-
- for (i = 0; i < r0->lo_nr; ++i) {
- if (r0->lo_sub[i] == NULL)
- continue;
-
- subobj = lovsub2cl(r0->lo_sub[i]);
-
- rc = cl_object_find_cbdata(env, subobj, iter, data);
- if (rc != 0)
- break;
- }
-
- return rc;
-}
-
const static struct lov_layout_operations lov_dispatch[] = {
[LLT_EMPTY] = {
.llo_init = lov_init_empty,
.llo_lock_init = lov_lock_init_empty,
.llo_io_init = lov_io_init_empty,
.llo_getattr = lov_attr_get_empty,
- .llo_find_cbdata = lov_find_cbdata_empty
},
[LLT_RAID0] = {
.llo_init = lov_init_raid0,
.llo_lock_init = lov_lock_init_raid0,
.llo_io_init = lov_io_init_raid0,
.llo_getattr = lov_attr_get_raid0,
- .llo_find_cbdata = lov_find_cbdata_raid0
},
[LLT_RELEASED] = {
.llo_init = lov_init_released,
.llo_lock_init = lov_lock_init_empty,
.llo_io_init = lov_io_init_released,
.llo_getattr = lov_attr_get_empty,
- .llo_find_cbdata = lov_find_cbdata_empty
}
};
return maxbytes;
}
-static int lov_object_find_cbdata(const struct lu_env *env,
- struct cl_object *obj, ldlm_iterator_t iter,
- void *data)
-{
- int rc;
- ENTRY;
-
- /* call cl_object_find_cbdata for sub obj */
- rc = LOV_2DISPATCH(cl2lov(obj), llo_find_cbdata, env, obj, iter, data);
- RETURN(rc);
-}
-
static const struct cl_object_operations lov_ops = {
.coo_page_init = lov_page_init,
.coo_lock_init = lov_lock_init,
.coo_getstripe = lov_object_getstripe,
.coo_layout_get = lov_object_layout_get,
.coo_maxbytes = lov_object_maxbytes,
- .coo_find_cbdata = lov_object_find_cbdata,
.coo_fiemap = lov_object_fiemap,
};
int mdc_null_inode(struct obd_export *exp, const struct lu_fid *fid);
-int mdc_find_cbdata(struct obd_export *exp, const struct lu_fid *fid,
- ldlm_iterator_t it, void *data);
-
int mdc_intent_lock(struct obd_export *exp,
struct md_op_data *op_data,
struct lookup_intent *it,
RETURN(0);
}
-/* find any ldlm lock of the inode in mdc
- * return 0 not find
- * 1 find one
- * < 0 error */
-int mdc_find_cbdata(struct obd_export *exp,
- const struct lu_fid *fid,
- ldlm_iterator_t it, void *data)
-{
- struct ldlm_res_id res_id;
- int rc = 0;
- ENTRY;
-
- fid_build_reg_res_name((struct lu_fid*)fid, &res_id);
- rc = ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace, &res_id,
- it, data);
- if (rc == LDLM_ITER_STOP)
- RETURN(1);
- else if (rc == LDLM_ITER_CONTINUE)
- RETURN(0);
- RETURN(rc);
-}
-
static inline void mdc_clear_replay_flag(struct ptlrpc_request *req, int rc)
{
/* Don't hold error requests for replay. */
static struct md_ops mdc_md_ops = {
.m_getstatus = mdc_getstatus,
.m_null_inode = mdc_null_inode,
- .m_find_cbdata = mdc_find_cbdata,
.m_close = mdc_close,
.m_create = mdc_create,
.m_enqueue = mdc_enqueue,
EXPORT_SYMBOL(cl_object_getstripe);
/**
- * Find whether there is any callback data (ldlm lock) attached upon this
- * object.
- */
-int cl_object_find_cbdata(const struct lu_env *env, struct cl_object *obj,
- ldlm_iterator_t iter, void *data)
-{
- struct lu_object_header *top;
- int result = 0;
- ENTRY;
-
- top = obj->co_lu.lo_header;
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_find_cbdata != NULL) {
- result = obj->co_ops->coo_find_cbdata(env, obj, iter,
- data);
- if (result != 0)
- break;
- }
- }
- RETURN(result);
-}
-EXPORT_SYMBOL(cl_object_find_cbdata);
-
-/**
* Get fiemap extents from file object.
*
* \param env [in] lustre environment
{
LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
- LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
osc_object_ast_clear, osc);
return 0;
}
-/**
- * Find any ldlm lock covers the osc object.
- * \retval 0 not found
- * \retval 1 find one
- * \retval < 0 error
- */
-static int osc_object_find_cbdata(const struct lu_env *env,
- struct cl_object *obj, ldlm_iterator_t iter,
- void *data)
-{
- struct ldlm_res_id res_id;
- struct obd_device *obd;
- int rc = 0;
-
- ostid_build_res_name(&cl2osc(obj)->oo_oinfo->loi_oi, &res_id);
- obd = obj->co_lu.lo_dev->ld_obd;
- rc = ldlm_resource_iterate(obd->obd_namespace, &res_id, iter, data);
- if (rc == LDLM_ITER_STOP)
- return 1;
-
- if (rc == LDLM_ITER_CONTINUE)
- return 0;
-
- return rc;
-}
static int osc_object_fiemap(const struct lu_env *env, struct cl_object *obj,
struct ll_fiemap_info_key *fmkey,
.coo_attr_update = osc_attr_update,
.coo_glimpse = osc_object_glimpse,
.coo_prune = osc_object_prune,
- .coo_find_cbdata = osc_object_find_cbdata,
.coo_fiemap = osc_object_fiemap,
.coo_req_attr_set = osc_req_attr_set
};
}
run_test 402 "Return ENOENT to lod_generate_and_set_lovea"
+test_403() {
+ local file1=$DIR/$tfile.1
+ local file2=$DIR/$tfile.2
+ local tfile=$TMP/$tfile
+
+ rm -f $file1 $file2 $tfile
+
+ touch $file1
+ ln $file1 $file2
+
+ # 30 sec OBD_TIMEOUT in ll_getattr()
+ # right before populating st_nlink
+ $LCTL set_param fail_loc=0x80001409
+ stat -c %h $file1 > $tfile &
+
+ # create an alias, drop all locks and reclaim the dentry
+ < $file2
+ cancel_lru_locks mdc
+ cancel_lru_locks osc
+ sysctl -w vm.drop_caches=2
+
+ wait
+
+ [ `cat $tfile` -gt 0 ] || error "wrong nlink count: `cat $tfile`"
+
+ rm -f $tfile $file1 $file2
+}
+run_test 403 "i_nlink should not drop to zero due to aliasing"
+
#
# tests that do cleanup/setup should be run at the end
#