@@ -165,6 +165,7 @@ void req_capsule_shrink(struct req_capsule *pill,
extern struct req_format RQF_MDS_SWAP_LAYOUTS;
extern struct req_format RQF_MDS_REINT_MIGRATE;
extern struct req_format RQF_MDS_REINT_RESYNC;
+extern struct req_format RQF_MDS_RMFID;
/* MDS hsm formats */
extern struct req_format RQF_MDS_HSM_STATE_GET;
extern struct req_format RQF_MDS_HSM_STATE_SET;
@@ -236,6 +237,7 @@ void req_capsule_shrink(struct req_capsule *pill,
extern struct req_msg_field RMF_CLOSE_DATA;
extern struct req_msg_field RMF_FILE_SECCTX_NAME;
extern struct req_msg_field RMF_FILE_SECCTX;
+extern struct req_msg_field RMF_FID_ARRAY;
/*
* connection handle received in MDS_CONNECT request.
@@ -1039,6 +1039,8 @@ struct md_ops {
int (*unpackmd)(struct obd_export *exp, struct lmv_stripe_md **plsm,
const union lmv_mds_md *lmv, size_t lmv_size);
+ int (*rmfid)(struct obd_export *exp, struct fid_array *fa, int *rcs,
+ struct ptlrpc_request_set *set);
};
static inline struct md_open_data *obd_mod_alloc(void)
@@ -1663,6 +1663,18 @@ static inline int md_unpackmd(struct obd_export *exp,
return MDP(exp->exp_obd, unpackmd)(exp, plsm, lmm, lmm_size);
}
+static inline int md_rmfid(struct obd_export *exp, struct fid_array *fa,
+ int *rcs, struct ptlrpc_request_set *set)
+{
+ int rc;
+
+ rc = exp_check_ops(exp);
+ if (rc)
+ return rc;
+
+ return MDP(exp->exp_obd, rmfid)(exp, fa, rcs, set);
+}
+
/* OBD Metadata Support */
int obd_init_caches(void);
@@ -194,6 +194,7 @@
#define OBD_FAIL_MDS_CHANGELOG_INIT 0x151
#define OBD_FAIL_MDS_REINT_MULTI_NET 0x159
#define OBD_FAIL_MDS_REINT_MULTI_NET_REP 0x15a
+#define OBD_FAIL_MDS_RMFID_NET 0x166
/* layout lock */
#define OBD_FAIL_MDS_NO_LL_GETATTR 0x170
@@ -1180,6 +1180,57 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
return rc;
}
+int ll_rmfid(struct file *file, void __user *arg)
+{
+ const struct fid_array __user *ufa = arg;
+ struct fid_array *lfa = NULL;
+ size_t size;
+ unsigned int nr;
+ int i, rc, *rcs = NULL;
+
+ if (!capable(CAP_DAC_READ_SEARCH) &&
+ !(ll_i2sbi(file_inode(file))->ll_flags & LL_SBI_USER_FID2PATH))
+ return -EPERM;
+ /* Only need to get the buflen */
+ if (get_user(nr, &ufa->fa_nr))
+ return -EFAULT;
+ /* DoS protection */
+ if (nr > OBD_MAX_FIDS_IN_ARRAY)
+ return -E2BIG;
+
+ size = offsetof(struct fid_array, fa_fids[nr]);
+ lfa = kzalloc(size, GFP_NOFS);
+ if (!lfa)
+ return -ENOMEM;
+ rcs = kcalloc(nr, sizeof(int), GFP_NOFS);
+ if (!rcs) {
+ rc = -ENOMEM;
+ goto free_lfa;
+ }
+
+ if (copy_from_user(lfa, arg, size)) {
+ rc = -EFAULT;
+ goto free_rcs;
+ }
+
+ /* Call mdc_iocontrol */
+ rc = md_rmfid(ll_i2mdexp(file_inode(file)), lfa, rcs, NULL);
+ if (!rc) {
+ for (i = 0; i < nr; i++)
+ if (rcs[i])
+ lfa->fa_fids[i].f_ver = rcs[i];
+ if (copy_to_user(arg, lfa, size))
+ rc = -EFAULT;
+ }
+
+free_rcs:
+ kfree(rcs);
+free_lfa:
+ kfree(lfa);
+
+ return rc;
+}
+
/* This function tries to get a single name component,
* to send to the server. No actual path traversal involved,
* so we limit to NAME_MAX
@@ -1544,7 +1595,8 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ptlrpc_req_finished(request);
return rc;
}
-
+ case LL_IOC_RMFID:
+ return ll_rmfid(file, (void __user *)arg);
case LL_IOC_LOV_SWAP_LAYOUTS:
return -EPERM;
case IOC_OBD_STATFS:
@@ -2930,6 +2930,103 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp,
return -EINVAL;
}
+static int lmv_rmfid(struct obd_export *exp, struct fid_array *fa,
+ int *__rcs, struct ptlrpc_request_set *_set)
+{
+ struct obd_device *obddev = class_exp2obd(exp);
+ struct ptlrpc_request_set *set = _set;
+ struct lmv_obd *lmv = &obddev->u.lmv;
+ int tgt_count = lmv->desc.ld_tgt_count;
+ struct fid_array *fat, **fas = NULL;
+ int i, rc, **rcs = NULL;
+
+ if (!set) {
+ set = ptlrpc_prep_set();
+ if (!set)
+ return -ENOMEM;
+ }
+
+ /* split FIDs by targets */
+ fas = kcalloc(tgt_count, sizeof(fas), GFP_NOFS);
+ if (!fas) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rcs = kcalloc(tgt_count, sizeof(int *), GFP_NOFS);
+ if (!rcs) {
+ rc = -ENOMEM;
+ goto out_fas;
+ }
+
+ for (i = 0; i < fa->fa_nr; i++) {
+ unsigned int idx;
+
+ rc = lmv_fld_lookup(lmv, &fa->fa_fids[i], &idx);
+ if (rc) {
+ CDEBUG(D_OTHER, "can't lookup "DFID": rc = %d\n",
+ PFID(&fa->fa_fids[i]), rc);
+ continue;
+ }
+ LASSERT(idx < tgt_count);
+ if (!fas[idx])
+ fas[idx] = kzalloc(offsetof(struct fid_array,
+ fa_fids[fa->fa_nr]),
+ GFP_NOFS);
+ if (!fas[idx]) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ if (!rcs[idx])
+ rcs[idx] = kcalloc(fa->fa_nr, sizeof(int), GFP_NOFS);
+ if (!rcs[idx]) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ fat = fas[idx];
+ fat->fa_fids[fat->fa_nr++] = fa->fa_fids[i];
+ }
+
+ for (i = 0; i < tgt_count; i++) {
+ fat = fas[i];
+ if (!fat || fat->fa_nr == 0)
+ continue;
+ rc = md_rmfid(lmv->tgts[i]->ltd_exp, fat, rcs[i], set);
+ }
+
+ rc = ptlrpc_set_wait(NULL, set);
+ if (rc == 0) {
+ int j = 0;
+
+ for (i = 0; i < tgt_count; i++) {
+ fat = fas[i];
+ if (!fat || fat->fa_nr == 0)
+ continue;
+ /* copy FIDs back */
+ memcpy(fa->fa_fids + j, fat->fa_fids,
+ fat->fa_nr * sizeof(struct lu_fid));
+ /* copy rcs back */
+ memcpy(__rcs + j, rcs[i], fat->fa_nr * sizeof(**rcs));
+ j += fat->fa_nr;
+ }
+ }
+ if (set != _set)
+ ptlrpc_set_destroy(set);
+
+out:
+ for (i = 0; i < tgt_count; i++) {
+ if (fas)
+ kfree(fas[i]);
+ if (rcs)
+ kfree(rcs[i]);
+ }
+ kfree(rcs);
+out_fas:
+ kfree(fas);
+
+ return rc;
+}
+
/**
* Asynchronously set by key a value associated with a LMV device.
*
@@ -3517,6 +3614,7 @@ static int lmv_merge_attr(struct obd_export *exp,
.revalidate_lock = lmv_revalidate_lock,
.get_fid_from_lsm = lmv_get_fid_from_lsm,
.unpackmd = lmv_unpackmd,
+ .rmfid = lmv_rmfid,
};
static int __init lmv_init(void)
@@ -2585,6 +2585,79 @@ static int mdc_fsync(struct obd_export *exp, const struct lu_fid *fid,
return rc;
}
+struct mdc_rmfid_args {
+ int *mra_rcs;
+ int mra_nr;
+};
+
+int mdc_rmfid_interpret(const struct lu_env *env, struct ptlrpc_request *req,
+ void *args, int rc)
+{
+ struct mdc_rmfid_args *aa;
+ int *rcs, size;
+
+ if (!rc) {
+ aa = ptlrpc_req_async_args(aa, req);
+
+ size = req_capsule_get_size(&req->rq_pill, &RMF_RCS,
+ RCL_SERVER);
+ LASSERT(size == sizeof(int) * aa->mra_nr);
+ rcs = req_capsule_server_get(&req->rq_pill, &RMF_RCS);
+ LASSERT(rcs);
+ LASSERT(aa->mra_rcs);
+ LASSERT(aa->mra_nr);
+ memcpy(aa->mra_rcs, rcs, size);
+ }
+
+ return rc;
+}
+
+static int mdc_rmfid(struct obd_export *exp, struct fid_array *fa,
+ int *rcs, struct ptlrpc_request_set *set)
+{
+ struct ptlrpc_request *req;
+ struct mdc_rmfid_args *aa;
+ struct mdt_body *b;
+ struct lu_fid *tmp;
+ int rc, flen;
+
+ req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_RMFID);
+ if (!req)
+ return -ENOMEM;
+
+ flen = fa->fa_nr * sizeof(struct lu_fid);
+ req_capsule_set_size(&req->rq_pill, &RMF_FID_ARRAY,
+ RCL_CLIENT, flen);
+ req_capsule_set_size(&req->rq_pill, &RMF_FID_ARRAY,
+ RCL_SERVER, flen);
+ req_capsule_set_size(&req->rq_pill, &RMF_RCS,
+ RCL_SERVER, fa->fa_nr * sizeof(u32));
+ rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_RMFID);
+ if (rc) {
+ ptlrpc_request_free(req);
+ return rc;
+ }
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_FID_ARRAY);
+ memcpy(tmp, fa->fa_fids, flen);
+
+ mdc_pack_body(req, NULL, 0, 0, -1, 0);
+ b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY);
+ b->mbo_ctime = ktime_get_real_seconds();
+
+ ptlrpc_request_set_replen(req);
+
+ LASSERT(rcs);
+ aa = ptlrpc_req_async_args(aa, req);
+ aa->mra_rcs = rcs;
+ aa->mra_nr = fa->fa_nr;
+ req->rq_interpret_reply = mdc_rmfid_interpret;
+
+ ptlrpc_set_add_req(set, req);
+ ptlrpc_check_set(NULL, set);
+
+ return rc;
+}
+
static int mdc_import_event(struct obd_device *obd, struct obd_import *imp,
enum obd_import_event event)
{
@@ -2886,7 +2959,8 @@ static int mdc_cleanup(struct obd_device *obd)
.set_open_replay_data = mdc_set_open_replay_data,
.clear_open_replay_data = mdc_clear_open_replay_data,
.intent_getattr_async = mdc_intent_getattr_async,
- .revalidate_lock = mdc_revalidate_lock
+ .revalidate_lock = mdc_revalidate_lock,
+ .rmfid = mdc_rmfid,
};
static int __init mdc_init(void)
@@ -318,6 +318,21 @@
&RMF_DLM_REQ
};
+static const struct req_msg_field *mds_rmfid_client[] = {
+ &RMF_PTLRPC_BODY,
+ &RMF_MDT_BODY,
+ &RMF_FID_ARRAY,
+ &RMF_CAPA1,
+ &RMF_CAPA2,
+};
+
+static const struct req_msg_field *mds_rmfid_server[] = {
+ &RMF_PTLRPC_BODY,
+ &RMF_MDT_BODY,
+ &RMF_FID_ARRAY,
+ &RMF_RCS,
+};
+
static const struct req_msg_field *obd_connect_client[] = {
&RMF_PTLRPC_BODY,
&RMF_TGTUUID,
@@ -731,6 +746,7 @@
&RQF_MDS_HSM_ACTION,
&RQF_MDS_HSM_REQUEST,
&RQF_MDS_SWAP_LAYOUTS,
+ &RQF_MDS_RMFID,
&RQF_OST_CONNECT,
&RQF_OST_DISCONNECT,
&RQF_OST_QUOTACTL,
@@ -929,6 +945,10 @@ struct req_msg_field RMF_NAME =
DEFINE_MSGF("name", RMF_F_STRING, -1, NULL, NULL);
EXPORT_SYMBOL(RMF_NAME);
+struct req_msg_field RMF_FID_ARRAY =
+ DEFINE_MSGF("fid_array", 0, -1, NULL, NULL);
+EXPORT_SYMBOL(RMF_FID_ARRAY);
+
struct req_msg_field RMF_SYMTGT =
DEFINE_MSGF("symtgt", RMF_F_STRING, -1, NULL, NULL);
EXPORT_SYMBOL(RMF_SYMTGT);
@@ -1511,6 +1531,11 @@ struct req_format RQF_MDS_WRITEPAGE =
mdt_body_capa, mdt_body_only);
EXPORT_SYMBOL(RQF_MDS_WRITEPAGE);
+struct req_format RQF_MDS_RMFID =
+ DEFINE_REQ_FMT0("MDS_RMFID", mds_rmfid_client,
+ mds_rmfid_server);
+EXPORT_SYMBOL(RQF_MDS_RMFID);
+
struct req_format RQF_LLOG_ORIGIN_HANDLE_CREATE =
DEFINE_REQ_FMT0("LLOG_ORIGIN_HANDLE_CREATE",
llog_origin_handle_create_client, llogd_body_only);
@@ -96,6 +96,7 @@
{ MDS_HSM_CT_REGISTER, "mds_hsm_ct_register" },
{ MDS_HSM_CT_UNREGISTER, "mds_hsm_ct_unregister" },
{ MDS_SWAP_LAYOUTS, "mds_swap_layouts" },
+ { MDS_RMFID, "mds_rmfid" },
{ LDLM_ENQUEUE, "ldlm_enqueue" },
{ LDLM_CONVERT, "ldlm_convert" },
{ LDLM_CANCEL, "ldlm_cancel" },
@@ -178,7 +178,9 @@ void lustre_assert_wire_constants(void)
(long long)MDS_HSM_CT_UNREGISTER);
LASSERTF(MDS_SWAP_LAYOUTS == 61, "found %lld\n",
(long long)MDS_SWAP_LAYOUTS);
- LASSERTF(MDS_LAST_OPC == 62, "found %lld\n",
+ LASSERTF(MDS_RMFID == 62, "found %lld\n",
+ (long long)MDS_RMFID);
+ LASSERTF(MDS_LAST_OPC == 63, "found %lld\n",
(long long)MDS_LAST_OPC);
LASSERTF(REINT_SETATTR == 1, "found %lld\n",
(long long)REINT_SETATTR);
@@ -1443,6 +1443,7 @@ enum mds_cmd {
MDS_HSM_CT_REGISTER = 59,
MDS_HSM_CT_UNREGISTER = 60,
MDS_SWAP_LAYOUTS = 61,
+ MDS_RMFID = 62,
MDS_LAST_OPC
};
@@ -348,6 +348,7 @@ struct ll_ioc_lease_id {
#define LL_IOC_LMV_SETSTRIPE _IOWR('f', 240, struct lmv_user_md)
#define LL_IOC_LMV_GETSTRIPE _IOWR('f', 241, struct lmv_user_md)
+#define LL_IOC_RMFID _IOR('f', 242, struct fid_array)
#define LL_IOC_SET_LEASE _IOWR('f', 243, struct ll_ioc_lease)
#define LL_IOC_SET_LEASE_OLD _IOWR('f', 243, long)
#define LL_IOC_GET_LEASE _IO('f', 244)
@@ -2149,6 +2150,15 @@ struct lu_pcc_state {
char pccs_path[PATH_MAX];
};
+struct fid_array {
+ __u32 fa_nr;
+ /* make header's size equal lu_fid */
+ __u32 fa_padding0;
+ __u64 fa_padding1;
+ struct lu_fid fa_fids[0];
+};
+#define OBD_MAX_FIDS_IN_ARRAY 4096
+
/** @} lustreuser */
#endif /* _LUSTRE_USER_H */