add support for ost-authorization-revocation and fid verification.
if (rc)
GOTO(out, rc);
- rc = obd_setattr(exp, oa, lsm, NULL);
+ rc = obd_setattr(exp, oa, lsm, NULL, NULL);
cmobd_free_lsm(&lsm);
out:
static int cobd_dt_setattr(struct obd_export *exp, struct obdo *obdo,
struct lov_stripe_md *ea,
- struct obd_trans_info *oti)
+ struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
struct obd_device *obd = class_exp2obd(exp);
struct obd_export *cobd_exp;
RETURN(-EINVAL);
}
cobd_exp = cobd_get_exp(obd);
- rc = obd_setattr(cobd_exp, obdo, ea, oti);
+ rc = obd_setattr(cobd_exp, obdo, ea, oti, capa);
RETURN(rc);
}
extern void lustre_swab_ptlbd_rsp (struct ptlbd_rsp *r);
-#define CAPA_KEY_LEN 16
-#define CAPA_DIGEST_SIZE 16
+#define CAPA_KEY_LEN 20 /* SHA1_DIGEST_LENGTH */
+#define CAPA_DIGEST_SIZE 20 /* SHA1_DIGEST_LENGTH */
struct lustre_capa {
- __u32 lc_uid; /* uid */
+ __u32 lc_uid; /* uid, mapped uid */
+ __u32 lc_ruid; /* remote uid on client */
__u32 lc_op; /* operations allowed */
__u64 lc_ino; /* inode# */
__u32 lc_mdsid; /* mds# */
struct inode *inode; /* this should be always valid
* if c_refc > 0 */
struct lustre_handle handle; /* handle of mds_file_data */
+#if 0 /* TODO: support multi mount point */
struct list_head *list; /* the capa list belong to this client */
struct timer_list *timer; /* timer belong to this client */
+#endif
};
struct filter_capa {
FILTER_CAPA = 2,
};
+#define DEBUG_CAPA(level, capa, fmt, args...) \
+do { \
+CDEBUG(level, fmt " capa@%p uid %u op %u ino "LPU64" mdsid %d keyid %d " \
+ "expiry "LPU64" flags %u\n", \
+ ##args, capa, (capa)->lc_uid, (capa)->lc_op, (capa)->lc_ino, \
+ (capa)->lc_mdsid, (capa)->lc_keyid, (capa)->lc_expiry, \
+ (capa)->lc_flags); \
+} while (0)
+
+#define DEBUG_CAPA_KEY(level, key, fmt, args...) \
+do { \
+CDEBUG(level, fmt " capa key@%p mdsid %d keyid %d expiry "LPU64"\n", \
+ ##args, key, (key)->lk_mdsid, (key)->lk_keyid, (key)->lk_expiry); \
+} while (0)
+
+#define DEBUG_MDS_CAPA_KEY(level, mkey, fmt, args...) \
+do { \
+CDEBUG(level, fmt " capa key@%p mdsid %d keyid %d expiry "LPU64"\n", \
+ ##args, mkey, le32_to_cpu((mkey)->k_key->lk_mdsid), \
+ le32_to_cpu((mkey)->k_key->lk_keyid), \
+ le64_to_cpu((mkey)->k_key->lk_expiry)); \
+} while (0)
+
extern spinlock_t capa_lock;
extern struct hlist_head *capa_hash;
extern struct list_head capa_list[];
/* struct lustre_capa.lc_flags */
#define CAPA_FL_NOROUND 0x001 /* capa expiry not rounded */
+#define CAPA_FL_REMUID 0x002 /* remote uid */
static inline unsigned long capa_pre_expiry(struct lustre_capa *capa)
{
static inline int
capa_key_cmp(struct lustre_capa_key *k1, struct lustre_capa_key *k2)
{
- return le32_to_cpu(k1->lk_keyid) - le32_to_cpu(k2->lk_keyid);
+ return k1->lk_keyid - k2->lk_keyid;
}
static inline unsigned long
{
/* sec -> jiffies */
struct timeval tv;
+ unsigned long timeout;
do_gettimeofday(&tv);
- return jiffies + ((unsigned long)expiry - tv.tv_sec) * HZ;
+ timeout = jiffies + ((unsigned long)expiry - tv.tv_sec) * HZ;
+ return timeout;
}
struct mds_capa_key {
int (*o_destroy)(struct obd_export *exp, struct obdo *oa,
struct lov_stripe_md *ea, struct obd_trans_info *oti);
int (*o_setattr)(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *ea, struct obd_trans_info *oti);
+ struct lov_stripe_md *ea, struct obd_trans_info *oti,
+ struct lustre_capa *capa);
int (*o_getattr)(struct obd_export *exp, struct obdo *oa,
struct lov_stripe_md *ea);
int (*o_getattr_async)(struct obd_export *exp, struct obdo *oa,
static inline int obd_setattr(struct obd_export *exp, struct obdo *obdo,
struct lov_stripe_md *ea,
- struct obd_trans_info *oti)
+ struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
int rc;
ENTRY;
EXP_CHECK_OP(exp, setattr);
OBD_COUNTER_INCREMENT(exp->exp_obd, setattr);
- rc = OBP(exp->exp_obd, setattr)(exp, obdo, ea, oti);
+ rc = OBP(exp->exp_obd, setattr)(exp, obdo, ea, oti, capa);
RETURN(rc);
}
static inline int obd_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
oa.o_valid = OBD_MD_FLID;
obdo_from_inode(&oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
OBD_MD_FLMTIME | OBD_MD_FLCTIME);
- rc = obd_setattr(sbi->ll_dt_exp, &oa, lsm, NULL);
+ rc = obd_setattr(sbi->ll_dt_exp, &oa, lsm, NULL, NULL);
if (rc)
CERROR("obd_setattr fails: rc=%d\n", rc);
}
{
struct obd_capa *ocapa;
int expired = 0;
+ unsigned long expiry;
ENTRY;
spin_lock(&capa_lock);
ocapa = list_entry(ll_capa_list->next, struct obd_capa, c_list);
expired = __capa_is_to_expire(ocapa);
+ if (!expired && !timer_pending(&ll_capa_timer)) {
+ /* the expired capa has been put, so set the timer to
+ * the expired of the next capa */
+ expiry = expiry_to_jiffies(ocapa->c_capa.lc_expiry);
+ mod_timer(&ll_capa_timer, expiry);
+ CDEBUG(D_INFO, "ll_capa_timer new expiry: %lu\n", expiry);
+ }
}
spin_unlock(&capa_lock);
while (1) {
struct l_wait_info lwi = { 0 };
struct obd_capa *ocapa, *next = NULL;
- int sleep = CAPA_PRE_EXPIRY;
+ unsigned long expiry, sleep = CAPA_PRE_EXPIRY;
l_wait_event(ll_capa_thread.t_ctl_waitq,
(have_expired_capa() || ll_capa_check_stop()),
}
}
if (next) {
- mod_timer(&ll_capa_timer,
- expiry_to_jiffies(next->c_capa.lc_expiry));
+ expiry = expiry_to_jiffies(next->c_capa.lc_expiry);
+ mod_timer(&ll_capa_timer, expiry);
+ CDEBUG(D_INFO, "ll_capa_timer new expiry: %lu\n", expiry);
if (next->c_capa.lc_flags & CAPA_FL_NOROUND)
sleep = CAPA_PRE_EXPIRY_NOROUND;
}
if (!och->och_capa)
rc = -ENOMEM;
+ DEBUG_CAPA(D_INFO, capa, "ll_set_och_capa");
+
expiry = expiry_to_jiffies(capa->lc_expiry - capa_pre_expiry(capa));
+
+ spin_lock(&capa_lock);
if (time_before(expiry, ll_capa_timer.expires) ||
- !timer_pending(&ll_capa_timer))
+ !timer_pending(&ll_capa_timer)) {
mod_timer(&ll_capa_timer, expiry);
+ CDEBUG(D_INFO, "ll_capa_timer new expiry: %lu\n", expiry);
+ }
+ spin_unlock(&capa_lock);
RETURN(rc);
}
+
OBD_FREE(lli->lli_trunc_capa,
sizeof(*trunc_capa));
lli->lli_trunc_capa = trunc_capa;
+ DEBUG_CAPA(D_INFO, trunc_capa, "truncate");
}
spin_unlock(&lli->lli_lock);
}
obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
OBD_MD_FLMTIME | OBD_MD_FLCTIME);
- rc = obd_setattr(sbi->ll_dt_exp, oa, lsm, NULL);
+ rc = obd_setattr(sbi->ll_dt_exp, oa, lsm, NULL, NULL);
obdo_free(oa);
if (rc)
CERROR("obd_setattr fails: rc = %d\n", rc);
oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | OBD_MD_FLGROUP
| OBD_MD_FLIFID;
- rc = obd_setattr(sbi->ll_dt_exp, oa, lsm, NULL);
+ rc = obd_setattr(sbi->ll_dt_exp, oa, lsm, NULL, NULL);
obdo_free(oa);
if (rc) {
if (rc != -EPERM && rc != -EACCES)
}
static int lov_setattr(struct obd_export *exp, struct obdo *src_oa,
- struct lov_stripe_md *lsm, struct obd_trans_info *oti)
+ struct lov_stripe_md *lsm, struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
struct lov_request_set *set;
struct lov_obd *lov;
req = list_entry(pos, struct lov_request, rq_link);
rc = obd_setattr(lov->tgts[req->rq_idx].ltd_exp, req->rq_oa,
- NULL, NULL);
+ NULL, NULL, NULL);
err = lov_update_common_set(set, req, rc);
if (err) {
CERROR("error: setattr objid "LPX64" subobj "
if (rc)
RETURN(rc);
+ DEBUG_CAPA(D_INFO, capa, "capa renewal");
+
+ spin_lock(&capa_lock);
expiry = expiry_to_jiffies(capa->lc_expiry - capa_pre_expiry(capa));
if (time_before(expiry, ll_capa_timer.expires) ||
- !timer_pending(&ll_capa_timer))
+ !timer_pending(&ll_capa_timer)) {
mod_timer(&ll_capa_timer, expiry);
+ CDEBUG(D_INFO, "ll_capa_timer new timer: %lu\n", expiry);
+ }
+ spin_unlock(&capa_lock);
RETURN(rc);
}
int repsize[2] = {sizeof(struct mds_body), sizeof(struct lustre_capa)};
ENTRY;
- req->rq_replen = lustre_msg_size(1, repsize);
+ req->rq_replen = lustre_msg_size(2, repsize);
req->rq_interpret_reply = mdc_interpret_getattr;
ptlrpcd_add_req(req);
}
offset = reply_off + 1;
- rc = mds_pack_capa(obd, reqbody, req_capa, req->rq_repmsg,
+ rc = mds_pack_capa(obd, med, reqbody, req_capa, req,
&offset, body);
}
LASSERT(current->journal_info == NULL);
- EXIT;
-
/* If we're DISCONNECTing, the mds_export_data is already freed */
if (!rc && req->rq_reqmsg->opc != MDS_DISCONNECT) {
struct mds_export_data *med = &req->rq_export->exp_mds_data;
target_send_reply(req, rc, fail);
- return 0;
+ RETURN(0);
}
/* Update the server data on disk. This stores the new mount_count and also the
if (rc)
return rc;
- obd->u.mds.mds_capa_stat = val;
+ mds_update_capa_stat(obd, val);
return count;
}
if (rc)
return rc;
- obd->u.mds.mds_capa_timeout = val;
+ mds_update_capa_timeout(obd, val);
return count;
}
if (rc)
return rc;
- obd->u.mds.mds_capa_key_timeout = val;
- return count;
+ rc = mds_update_capa_key_timeout(obd, val);
+ return rc ?: count;
}
struct lprocfs_vars lprocfs_mds_obd_vars[] = {
} mds_eck_ctl;
static LIST_HEAD(mds_capa_key_list);
-static LIST_HEAD(mds_expired_capa_keys);
static spinlock_t mds_capa_lock; /* protect capa and capa key */
struct timer_list mds_eck_timer;
-#define CUR_MDS_CAPA_KEY(mds) mds->mds_capa_keys[mds->mds_capa_key_idx]
+#define CAPA_KEY_JIFFIES(key) \
+ expiry_to_jiffies(le64_to_cpu((key)->k_key->lk_expiry))
+
+#define CUR_MDS_CAPA_KEY(mds) (mds)->mds_capa_keys[(mds)->mds_capa_key_idx]
#define CUR_CAPA_KEY(mds) CUR_MDS_CAPA_KEY(mds).k_key
#define CUR_CAPA_KEY_ID(mds) CUR_MDS_CAPA_KEY(mds).k_key->lk_keyid
-#define CUR_CAPA_KEY_EXPIRY(mds) expiry_to_jiffies(CUR_CAPA_KEY(mds)->lk_expiry)
#define CUR_CAPA_KEY_LIST(mds) CUR_MDS_CAPA_KEY(mds).k_list
+#define CUR_CAPA_KEY_EXPIRY(mds) le64_to_cpu(CUR_CAPA_KEY(mds)->lk_expiry)
+#define CUR_CAPA_KEY_JIFFIES(mds) CAPA_KEY_JIFFIES(&CUR_MDS_CAPA_KEY(mds))
static int mds_write_capa_key(struct obd_device *obd, int force_sync)
{
static inline int
mds_capa_key_cmp(struct mds_obd *mds)
{
- return capa_key_cmp(mds->mds_capa_keys[0].k_key,
- mds->mds_capa_keys[1].k_key);
+ return le32_to_cpu(mds->mds_capa_keys[0].k_key->lk_keyid) -
+ le32_to_cpu(mds->mds_capa_keys[1].k_key->lk_keyid);
}
static void
__u64 expiry_rounded;
if (CUR_CAPA_KEY(mds))
- keyid = le32_to_cpu(CUR_CAPA_KEY(mds)->lk_keyid) + 1;
+ keyid = le32_to_cpu(CUR_CAPA_KEY_ID(mds)) + 1;
+ spin_lock(&mds_capa_lock);
expiry_rounded = round_expiry(mds->mds_capa_key_timeout);
+ spin_unlock(&mds_capa_lock);
key->lk_mdsid = cpu_to_le32(mds->mds_num);
key->lk_keyid = cpu_to_le32(keyid);
struct mds_capa_key *tmp;
list_for_each_entry_reverse(tmp, head, k_list) {
- if (key->k_key->lk_expiry > tmp->k_key->lk_expiry) {
- list_add(&key->k_list, &tmp->k_list);
+ if (le64_to_cpu(key->k_key->lk_expiry) <
+ le64_to_cpu(tmp->k_key->lk_expiry)) {
+ /* put key before tmp */
+ list_add_tail(&key->k_list, &tmp->k_list);
return;
}
}
- list_add(&key->k_list, head);
+ list_add_tail(&key->k_list, head);
}
int mds_read_capa_key(struct obd_device *obd, struct file *file)
struct mds_obd *mds = &obd->u.mds;
struct lustre_capa_key *key;
unsigned long capa_keys_size = file->f_dentry->d_inode->i_size;
+ unsigned long expiry;
int i = 0, rc = 0;
ENTRY;
mds->mds_capa_key_idx = 1;
}
+ expiry = CUR_CAPA_KEY_JIFFIES(mds);
spin_lock(&mds_capa_lock);
- if (time_before(CUR_CAPA_KEY_EXPIRY(mds), mds_eck_timer.expires)
- || !timer_pending(&mds_eck_timer))
- mod_timer(&mds_eck_timer, CUR_CAPA_KEY_EXPIRY(mds));
-
+ if (time_before(expiry, mds_eck_timer.expires) ||
+ !timer_pending(&mds_eck_timer))
+ mod_timer(&mds_eck_timer, expiry);
list_add_capa_key(&CUR_MDS_CAPA_KEY(mds), &mds_capa_key_list);
spin_unlock(&mds_capa_lock);
out:
struct mds_obd *mds = &obd->u.mds;
int i;
+ del_timer(&mds_eck_timer);
spin_lock(&mds_capa_lock);
if (CUR_CAPA_KEY(mds))
list_del_init(&CUR_CAPA_KEY_LIST(mds));
rc = obd_set_info(mds->mds_dt_exp, strlen("capa_key"), "capa_key",
sizeof(*key), key);
- if (rc)
- CERROR("obd_set_info capa_key failed: rc = %d\n", rc);
-
RETURN(rc);
}
int force_sync)
{
struct mds_obd *mds = &obd->u.mds;
- int to_update = mds->mds_capa_key_idx ^ 1;
+ int to_update = !mds->mds_capa_key_idx;
struct lustre_capa_key *key = mds->mds_capa_keys[to_update].k_key;
__u32 keyid;
- int rc = 0;
+ unsigned long expiry;
+ int rc, rc2;
ENTRY;
LASSERT(mkey != &mds->mds_capa_keys[to_update]);
keyid = le32_to_cpu(key->lk_keyid);
rc = mds_set_capa_key(obd, key);
- if (rc) {
+ if (rc)
+ /* XXX: anyway, it will be replayed */
CERROR("error set capa key(id %u), err = %d\n", keyid, rc);
- GOTO(out, rc);
- }
-
- CDEBUG(D_INFO, "MDS capa_keyid is %u\n", keyid);
- rc = mds_write_capa_key(obd, 1);
- if (rc)
- GOTO(out, rc);
+ rc2 = mds_write_capa_key(obd, 1);
+ if (rc2)
+ GOTO(out, rc2);
- CDEBUG(D_INFO, "wrote capa keyid %u: err = %d\n", keyid, rc);
+ CDEBUG(D_INFO, "wrote capa keyid %u\n", keyid);
spin_lock(&mds_capa_lock);
list_del_init(&CUR_CAPA_KEY_LIST(mds));
mds->mds_capa_key_idx = to_update;
+ expiry = CUR_CAPA_KEY_JIFFIES(mds);
list_add_capa_key(&CUR_MDS_CAPA_KEY(mds), &mds_capa_key_list);
+
+ if (time_before(expiry, mds_eck_timer.expires) ||
+ !timer_pending(&mds_eck_timer))
+ mod_timer(&mds_eck_timer, expiry);
spin_unlock(&mds_capa_lock);
- /* TODO: update timer here */
+ DEBUG_MDS_CAPA_KEY(D_INFO, &CUR_MDS_CAPA_KEY(mds),
+ "mds_update_capa_key");
out:
- RETURN(rc);
+ RETURN(rc2);
}
static inline int have_expired_capa_key(void)
if (!list_empty(&mds_capa_key_list)) {
key = list_entry(mds_capa_key_list.next, struct mds_capa_key,
k_list);
- expired = time_before(expiry_to_jiffies(key->k_key->lk_expiry),
- jiffies);
+ /* expiry is in sec, so in case it misses, the result will
+ * minus HZ and then compare with jiffies. */
+ expired = time_before(CAPA_KEY_JIFFIES(key) - HZ, jiffies);
}
spin_unlock(&mds_capa_lock);
{
struct thread_ctl *ctl = arg;
unsigned long flags;
+ int rc;
ENTRY;
- {
- char name[sizeof(current->comm)];
- snprintf(name, sizeof(name) - 1, "mds_ck");
- kportal_daemonize(name);
- }
+ lock_kernel();
+ ptlrpc_daemonize();
SIGNAL_MASK_LOCK(current, flags);
sigfillset(¤t->blocked);
RECALC_SIGPENDING;
SIGNAL_MASK_UNLOCK(current, flags);
+ THREAD_NAME(current->comm, sizeof(current->comm), "mds_ck");
+ unlock_kernel();
/*
* letting starting function know, that we are ready and control may be
spin_lock(&mds_capa_lock);
list_for_each_entry_safe(key, tmp, &mds_capa_key_list, k_list) {
- if (time_after(expiry_to_jiffies(key->k_key->lk_expiry),
- jiffies)) {
+ if (time_after(CAPA_KEY_JIFFIES(key), jiffies)) {
next = key;
break;
}
spin_unlock(&mds_capa_lock);
- CDEBUG(D_INFO, "mds capa key expired, wake up updating "
- "thread: mds #%u, key #%u\n",
+ CDEBUG(D_INFO, "mds capa key expired: "
+ "mds #%u, key #%u\n",
le32_to_cpu(key->k_key->lk_mdsid),
le32_to_cpu(key->k_key->lk_keyid));
- mds_update_capa_key(key->k_obd, key, 1);
+ rc = mds_update_capa_key(key->k_obd, key, 1);
spin_lock(&mds_capa_lock);
}
if (next)
- mod_timer(&mds_eck_timer,
- expiry_to_jiffies(next->k_key->lk_expiry));
+ mod_timer(&mds_eck_timer, CAPA_KEY_JIFFIES(next));
spin_unlock(&mds_capa_lock);
}
EXIT;
}
-int mds_pack_capa(struct obd_device *obd, struct mds_body *req_body,
- struct lustre_capa *req_capa, struct lustre_msg *repmsg,
- int *offset, struct mds_body *body)
+void mds_update_capa_stat(struct obd_device *obd, int stat)
+{
+ struct mds_obd *mds = &obd->u.mds;
+
+ spin_lock(&mds_capa_lock);
+ mds->mds_capa_stat = stat;
+ spin_unlock(&mds_capa_lock);
+}
+
+void mds_update_capa_timeout(struct obd_device *obd, unsigned long timeout)
+{
+ struct mds_obd *mds = &obd->u.mds;
+
+ spin_lock(&mds_capa_lock);
+ mds->mds_capa_timeout = timeout;
+ /* XXX: update all capabilities in cache if their expiry too long */
+ spin_unlock(&mds_capa_lock);
+}
+
+int mds_update_capa_key_timeout(struct obd_device *obd, unsigned long timeout)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct timeval tv;
+ int rc;
+ ENTRY;
+
+ do_gettimeofday(&tv);
+
+ spin_lock(&mds_capa_lock);
+ mds->mds_capa_key_timeout = timeout;
+ if (CUR_CAPA_KEY_EXPIRY(mds) < tv.tv_sec + timeout) {
+ spin_unlock(&mds_capa_lock);
+ RETURN(0);
+ }
+ spin_unlock(&mds_capa_lock);
+
+ rc = mds_update_capa_key(obd, &CUR_MDS_CAPA_KEY(mds), 1);
+
+ RETURN(rc);
+}
+
+static void mds_capa_reverse_map(struct mds_export_data *med,
+ struct lustre_capa *capa)
+{
+ uid_t uid;
+
+ if (!med->med_remote)
+ return;
+
+ ENTRY;
+ uid = mds_idmap_lookup_uid(med->med_idmap, 1, capa->lc_uid);
+ if (uid == MDS_IDMAP_NOTFOUND)
+ uid = med->med_nllu;
+ capa->lc_ruid = uid;
+ capa->lc_flags |= CAPA_FL_REMUID;
+ EXIT;
+}
+
+
+int mds_pack_capa(struct obd_device *obd, struct mds_export_data *med,
+ struct mds_body *req_body, struct lustre_capa *req_capa,
+ struct ptlrpc_request *req, int *offset, struct mds_body *body)
{
struct mds_obd *mds = &obd->u.mds;
struct lustre_capa *capa;
+ struct lustre_msg *repmsg = req->rq_repmsg;
struct obd_capa *ocapa;
__u8 key[CAPA_KEY_LEN]; /* key */
- int expired, rc = 0;
+ int stat, expired, rc = 0;
ENTRY;
- if (mds->mds_capa_stat == 0) {
+ spin_lock(&mds_capa_lock);
+ stat = mds->mds_capa_stat;
+ spin_unlock(&mds_capa_lock);
+
+ if (stat == 0) {
(*offset)++;
RETURN(0); /* capability is disabled */
}
if (!(req_capa->lc_op & mode)) {
CERROR("invalid capa to renew ino "LPD64
": op %d mismatch with mode %d\n",
- req_capa->lc_ino, req_capa->lc_op, mfd->mfd_mode);
+ req_capa->lc_ino, req_capa->lc_op,
+ mfd->mfd_mode);
RETURN(-EACCES);
}
}
}
memcpy(capa, req_capa, sizeof(*capa));
+ mds_capa_reverse_map(med, capa);
spin_lock(&mds_capa_lock);
capa->lc_keyid = le32_to_cpu(CUR_CAPA_KEY_ID(mds));
GOTO(err_capa_keyid, rc = -ENOENT);
}
-#if 0
rc = mds_read_capa_key(obd, file);
if (rc) {
CERROR("cannot read %s: rc = %d\n", CAPA_KEYS, rc);
GOTO(err_capa_keyid, rc);
}
-#endif
/* reint fidext thumb by last fid after root and virt are initialized */
mds->mds_fidext_thumb = mds->mds_last_fid;
void mds_capa_key_timer_callback(unsigned long data);
int mds_capa_key_start_thread(void);
void mds_capa_key_stop_thread(void);
-int mds_pack_capa(struct obd_device *obd, struct mds_body *req_body,
- struct lustre_capa *req_capa, struct lustre_msg *repmsg,
- int *offset, struct mds_body *body);
+int mds_pack_capa(struct obd_device *obd, struct mds_export_data *med,
+ struct mds_body *req_body, struct lustre_capa *req_capa,
+ struct ptlrpc_request *req, int *offset,
+ struct mds_body *body);
+void mds_update_capa_stat(struct obd_device *obd, int stat);
+void mds_update_capa_timeout(struct obd_device *obd, unsigned long timeout);
+int mds_update_capa_key_timeout(struct obd_device *obd, unsigned long timeout);
#endif /* _MDS_INTERNAL_H */
if (size < 0)
CERROR("Can not get gskey from MDS ino %lu rc %d\n",
inode->i_ino, size);
- (*offset) += 2; /* XXX: ignore crypto in case size == 0 */
GOTO(out, rc = size);
}
if (le32_to_cpu(md_key->md_magic) != MD_KEY_MAGIC) {
obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLSIZE);
- rc = obd_setattr(mds->mds_dt_exp, oa, lsm, &oti);
+ rc = obd_setattr(mds->mds_dt_exp, oa, lsm, &oti, NULL);
if (rc) {
CERROR("error setting attrs for inode %lu: rc %d\n",
inode->i_ino, rc);
{
struct obd_device *obd = req->rq_export->exp_obd;
struct mds_obd *mds = mds_req2mds(req);
+ struct mds_export_data *med = &req->rq_export->u.eu_mds_data;
struct mds_file_data *mfd = NULL;
obd_id *ids = NULL;
unsigned mode;
.lc_mdsid = mds->mds_num,
};
- rc = mds_pack_capa(obd, NULL, &capa, req->rq_repmsg,
+ rc = mds_pack_capa(obd, med, NULL, &capa, req,
&reply_off, body);
if (rc < 0) {
CERROR("mds_pack_capa: rc = %d\n", rc);
int offset = 1;
LASSERT(capa.lc_mdsid == mds->mds_num);
- rc = mds_pack_capa(obd, NULL, &capa, req->rq_repmsg, &offset,
- body);
+ rc = mds_pack_capa(obd, med, NULL, &capa, req,
+ &offset, body);
if (rc < 0) {
CERROR("mds_pack_capa: rc = %d\n", rc);
RETURN(rc);
{
struct hlist_node *pos;
struct obd_capa *ocapa;
- ENTRY;
+ uid_t ouid;
CDEBUG(D_CACHE, "find_capa uid %u op %u mdsid "LPU64" ino %lu "
"type %d\n", uid, capa_op, mdsid, ino, type);
hlist_for_each_entry(ocapa, pos, head, c_hash) {
- if (ocapa->c_capa.lc_uid != uid)
- continue;
- if (ocapa->c_capa.lc_op != capa_op)
+ if (ocapa->c_capa.lc_ino != ino)
continue;
if (ocapa->c_capa.lc_mdsid != mdsid)
continue;
- if (ocapa->c_capa.lc_ino != ino)
+ if (ocapa->c_capa.lc_op != capa_op)
continue;
if (ocapa->c_type != type)
continue;
- RETURN(ocapa);
+
+ if (ocapa->c_type == CLIENT_CAPA &&
+ ocapa->c_capa.lc_flags & CAPA_FL_REMUID)
+ ouid = ocapa->c_capa.lc_ruid;
+ else
+ ouid = ocapa->c_capa.lc_uid;
+
+ if (ouid != uid)
+ continue;
+
+ return ocapa;
}
- RETURN(NULL);
+ return NULL;
}
inline void __capa_get(struct obd_capa *ocapa)
static struct obd_capa *alloc_capa(void)
{
struct obd_capa *ocapa;
- ENTRY;
OBD_SLAB_ALLOC(ocapa, capa_cachep, SLAB_NOFS, sizeof(*ocapa));
if (ocapa) {
INIT_LIST_HEAD(&ocapa->c_list);
}
- RETURN(ocapa);
+ return ocapa;
}
static void destroy_capa(struct obd_capa *ocapa)
struct hlist_node *pos, *n;
hlist_for_each_entry_safe(ocapa, pos, n, capa_hash, c_hash) {
+ LASSERT(ocapa->c_type != CLIENT_CAPA);
hlist_del(&ocapa->c_hash);
list_del(&ocapa->c_list);
OBD_FREE(ocapa, sizeof(*ocapa));
list_add_tail(&ocapa->c_list, head);
}
-#define DEBUG_CAPA(level, ocapa, fmt, args...) \
-do { \
-CDEBUG(level, fmt " capa@%p uid %u op %u ino "LPU64" mdsid %d keyid %d " \
- "expiry "LPU64" flags %u type %d\n", \
- ##args, ocapa, ocapa->c_capa.lc_uid, ocapa->c_capa.lc_op, \
- ocapa->c_capa.lc_ino, ocapa->c_capa.lc_mdsid, ocapa->c_capa.lc_keyid, \
- ocapa->c_capa.lc_expiry, ocapa->c_capa.lc_flags, ocapa->c_type); \
-} while (0)
+static inline void do_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
+{
+ memcpy(&ocapa->c_capa, capa, sizeof(*capa));
+}
static struct obd_capa *
-get_new_capa_locked(struct hlist_head *head, uid_t uid, int capa_op,__u64 mdsid,
- unsigned long ino, int type, struct lustre_capa *capa,
+get_new_capa_locked(struct hlist_head *head, int type, struct lustre_capa *capa,
struct inode *inode, struct lustre_handle *handle)
{
+ uid_t uid = capa->lc_uid;
+ int capa_op = capa->lc_op;
+ __u64 mdsid = capa->lc_mdsid;
+ unsigned long ino = capa->lc_ino;
struct obd_capa *ocapa, *old;
ENTRY;
spin_lock(&capa_lock);
old = find_capa(head, uid, capa_op, mdsid, ino, type);
if (!old) {
- memcpy(&ocapa->c_capa, capa, sizeof(*capa));
+ do_update_capa(ocapa, capa);
ocapa->c_type = type;
+
if (type == CLIENT_CAPA) {
LASSERT(inode);
+ LASSERT(handle);
#ifdef __KERNEL__
igrab(inode);
#endif
ocapa->c_inode = inode;
memcpy(&ocapa->c_handle, handle, sizeof(*handle));
}
+
list_add_capa(ocapa, &capa_list[type]);
hlist_add_head(&ocapa->c_hash, capa_hash);
capa_count[type]++;
- DEBUG_CAPA(D_CACHE, ocapa, "get_new_capa_locked");
+
__capa_get(ocapa);
+
if (type != CLIENT_CAPA && capa_count[type] > CAPA_CACHE_SIZE) {
struct list_head *node = capa_list[type].next;
struct obd_capa *tcapa;
if (atomic_read(&tcapa->c_refc) > 0)
continue;
list_del(&tcapa->c_list);
+ hlist_del(&tcapa->c_hash);
destroy_capa(tcapa);
+ capa_count[type]--;
count++;
}
}
__capa_get(old);
spin_unlock(&capa_lock);
+
destroy_capa(ocapa);
- ocapa = old;
- RETURN(ocapa);
+ RETURN(old);
}
static struct obd_capa *
RETURN(ocapa);
if (capa)
- ocapa = get_new_capa_locked(head, uid, capa_op, mdsid, ino,
- type, capa, inode, handle);
+ ocapa = get_new_capa_locked(head, type, capa, inode, handle);
RETURN(ocapa);
}
EXIT;
}
-static inline void __update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
-{
- memcpy(&ocapa->c_capa, capa, sizeof(*capa));
-}
-
static int update_capa_locked(struct lustre_capa *capa, int type)
{
uid_t uid = capa->lc_uid;
spin_lock(&capa_lock);
ocapa = find_capa(head, uid, capa_op, mdsid, ino, type);
if (ocapa)
- __update_capa(ocapa, capa);
+ do_update_capa(ocapa, capa);
spin_unlock(&capa_lock);
- if (ocapa == NULL && type == MDS_CAPA)
- ocapa = get_new_capa_locked(head, uid, capa_op, mdsid, ino, type,
- capa, NULL, NULL);
+ if (ocapa == NULL && type == MDS_CAPA) {
+ ocapa = get_new_capa_locked(head, type, capa, NULL, NULL);
+ capa_put(ocapa, type);
+ }
RETURN(ocapa ? 0 : -ENOENT);
}
.offset = (unsigned long)(capa) % PAGE_SIZE,
.length = sizeof(struct lustre_capa_data),
};
- ENTRY;
LASSERT(tfm);
crypto_hmac(tfm, key, &keylen, &sl, 1, capa->lc_hmac);
- EXIT;
}
void capa_dup(void *dst, struct obd_capa *ocapa)
int pre_expiry = capa_pre_expiry(&ocapa->c_capa);
do_gettimeofday(&tv);
- return (ocapa->c_capa.lc_expiry - pre_expiry < tv.tv_sec)? 1 : 0;
+ return (ocapa->c_capa.lc_expiry - pre_expiry - 1 <= tv.tv_sec)? 1 : 0;
}
int capa_is_to_expire(struct obd_capa *ocapa)
}
static int echo_setattr(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *md, struct obd_trans_info *oti)
+ struct lov_stripe_md *md, struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
struct obd_device *obd = class_exp2obd(exp);
rc = echo_get_object (&eco, obd, &data->ioc_obdo1);
if (rc == 0) {
rc = obd_setattr(ec->ec_exp, &data->ioc_obdo1,
- eco->eco_lsm, NULL);
+ eco->eco_lsm, NULL, NULL);
echo_put_object(eco);
}
GOTO(out, rc);
filter_cleanup_groups(obd);
filter_free_server_data(filter);
- filter_free_capa_keys(filter);
pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+
+ filter_free_capa_keys(filter);
}
static void filter_set_last_id(struct filter_obd *filter, int group, obd_id id)
/* this is called from filter_truncate() until we have filter_punch() */
int filter_setattr(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *md, struct obd_trans_info *oti)
+ struct lov_stripe_md *md, struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
struct ldlm_res_id res_id = { .name = { oa->o_id, 0, oa->o_gr, 0 } };
struct ldlm_valblock_ops *ns_lvbo;
if (IS_ERR(dentry))
GOTO(out_pop, rc = PTR_ERR(dentry));
+ rc = filter_verify_capa(OBD_BRW_WRITE, exp, dentry->d_inode, capa);
+ if (rc)
+ RETURN(rc);
lock_kernel();
/* setting objects attributes (including owner/group) */
CDEBUG(D_INODE, "calling truncate for object "LPU64", valid = "LPU64", "
"o_size = "LPD64"\n", oa->o_id, oa->o_valid, start);
- error = filter_verify_capa(OBD_BRW_WRITE, exp, capa);
- if (error)
- RETURN(error);
oa->o_size = start;
- error = filter_setattr(exp, oa, NULL, oti);
+ error = filter_setattr(exp, oa, NULL, oti, capa);
RETURN(error);
}
{
struct filter_capa_key *key, *n;
+ spin_lock(&filter->fo_capa_lock);
list_for_each_entry_safe(key, n, &filter->fo_capa_keys, k_list) {
- list_del(&key->k_list);
+ list_del_init(&key->k_list);
OBD_FREE(key, sizeof(*key));
}
+ spin_unlock(&filter->fo_capa_lock);
}
int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *key)
spin_lock(&filter->fo_capa_lock);
list_for_each_entry(tmp, &filter->fo_capa_keys, k_list) {
- if (tmp->k_key.lk_mdsid == le32_to_cpu(key->lk_mdsid)) {
- if (rkey == NULL)
- rkey = tmp;
- else
- bkey = tmp;
- }
+ if (tmp->k_key.lk_mdsid != le32_to_cpu(key->lk_mdsid))
+ continue;
+
+ if (rkey == NULL)
+ rkey = tmp;
+ else
+ bkey = tmp;
}
spin_unlock(&filter->fo_capa_lock);
bkey = tmp;
}
- if (!bkey || !tmp) {
+ if (bkey) {
+ tmp = bkey;
+ } else {
OBD_ALLOC(tmp, sizeof(*tmp));
if (!tmp)
GOTO(out, rc = -ENOMEM);
-
- spin_lock(&filter->fo_capa_lock);
- list_add_tail(&tmp->k_list, &filter->fo_capa_keys);
- spin_unlock(&filter->fo_capa_lock);
}
/* fields in lustre_capa_key are in cpu order */
+ spin_lock(&filter->fo_capa_lock);
tmp->k_key.lk_mdsid = le32_to_cpu(key->lk_mdsid);
tmp->k_key.lk_keyid = le32_to_cpu(key->lk_keyid);
tmp->k_key.lk_expiry = le64_to_cpu(key->lk_expiry);
memcpy(&tmp->k_key.lk_key, key->lk_key, sizeof(key->lk_key));
+ if (!bkey)
+ list_add_tail(&tmp->k_list, &filter->fo_capa_keys);
+ spin_unlock(&filter->fo_capa_lock);
+
+ DEBUG_CAPA_KEY(D_INFO, &tmp->k_key, "filter_update_capa_key");
out:
RETURN(rc);
}
-int filter_verify_capa(int cmd, struct obd_export *exp,
+int filter_verify_capa(int cmd, struct obd_export *exp, struct inode *inode,
struct lustre_capa *capa)
{
struct obd_device *obd = exp->exp_obd;
struct filter_obd *filter = &obd->u.filter;
struct obd_capa *ocapa;
struct lustre_capa tcapa;
+ struct lustre_id fid;
struct filter_capa_key *rkey = NULL, *bkey = NULL, *tmp;
__u8 hmac_key[CAPA_KEY_LEN];
int rc = 0;
if (capa == NULL)
RETURN(-EACCES);
- if (cmd == OBD_BRW_WRITE && !(capa->lc_op & MAY_WRITE))
+ if (cmd == OBD_BRW_WRITE && capa->lc_op != MAY_WRITE)
RETURN(-EACCES);
if (cmd == OBD_BRW_READ && !(capa->lc_op & (MAY_WRITE | MAY_READ)))
RETURN(-EACCES);
if (OBD_FAIL_CHECK(OBD_FAIL_FILTER_VERIFY_CAPA))
RETURN(-EACCES);
- /* TODO: get fid from EA, and verify that against capa */
+ rc = fsfilt_get_md(obd, inode, &fid, sizeof(fid), EA_SID);
+ if (rc < 0) {
+ CERROR("get fid from object failed! rc:%d\n", rc);
+ RETURN(rc);
+ } else if (rc > 0) {
+ if (capa->lc_mdsid != id_group(&fid) ||
+ capa->lc_ino != id_ino(&fid))
+ RETURN(-EINVAL);
+ }
if (capa_expired(capa))
RETURN(-ESTALE);
struct obdo *oa, struct obd_trans_info *oti);
int filter_setattr(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *md, struct obd_trans_info *oti);
+ struct lov_stripe_md *md, struct obd_trans_info *oti,
+ struct lustre_capa *capa);
int filter_create_object(struct obd_device *obd, struct obdo *oa);
int filter_init_capa_keys(struct obd_device *obd);
void filter_free_capa_keys(struct filter_obd *filter);
int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *key);
-int filter_verify_capa(int cmd, struct obd_export *exp, struct lustre_capa *capa);
+int filter_verify_capa(int cmd, struct obd_export *exp, struct inode *inode,
+ struct lustre_capa *capa);
#endif
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_remote *nb,
struct niobuf_local *res,
- struct obd_trans_info *oti)
+ struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
struct obd_device *obd = exp->exp_obd;
struct lvfs_run_ctxt saved;
inode = dentry->d_inode;
+ rc = filter_verify_capa(cmd, exp, inode, capa);
+ if (rc)
+ return rc;
+
fsfilt_check_slow(now, obd_timeout, "preprw_read setup");
for (i = 0, lnb = res, rnb = nb; i < obj->ioo_bufcnt;
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_remote *nb,
struct niobuf_local *res,
- struct obd_trans_info *oti)
+ struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
int rc = 0, i, tot_bytes = 0, cleanup_phase = 0;
struct obd_device *obd = exp->exp_obd;
if (IS_ERR(dentry))
GOTO(cleanup, rc = PTR_ERR(dentry));
+ rc = filter_verify_capa(cmd, exp, dentry->d_inode, capa);
+ if (rc)
+ return rc;
+
cleanup_phase = 2;
fso.fso_dentry = dentry;
struct niobuf_remote *nb, struct niobuf_local *res,
struct obd_trans_info *oti, struct lustre_capa *capa)
{
- int rc;
-
- rc = filter_verify_capa(cmd, exp, capa);
- if (rc)
- return rc;
-
if (cmd == OBD_BRW_WRITE)
return filter_preprw_write(cmd, exp, oa, objcount, obj,
- niocount, nb, res, oti);
+ niocount, nb, res, oti, capa);
if (cmd == OBD_BRW_READ)
return filter_preprw_read(cmd, exp, oa, objcount, obj,
- niocount, nb, res, oti);
+ niocount, nb, res, oti, capa);
LBUG();
return -EPROTO;
}
static int osc_setattr(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *md, struct obd_trans_info *oti)
+ struct lov_stripe_md *md, struct obd_trans_info *oti,
+ struct lustre_capa *capa)
{
struct ptlrpc_request *request;
struct ost_body *body;
repbody = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*repbody));
memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_setattr(exp, &repbody->oa, NULL, oti);
+ req->rq_status = obd_setattr(exp, &repbody->oa, NULL, oti, NULL);
RETURN(0);
}
} else if (keylen == 9 && strcmp(key, "audit_obj") == 0) {
lustre_swab_reqbuf(req, 1, sizeof(struct obdo),
lustre_swab_obdo);
- } else if (keylen == 8 && strcmp(key, "capa_key") == 0) {
+ } else if (keylen == 8 && memcmp(key, "capa_key", 8) == 0) {
lustre_swab_reqbuf(req, 1, sizeof(struct lustre_capa_key),
lustre_swab_lustre_capa_key);
}
(unsigned long long)(int)sizeof(((struct llogd_conn_body *)0)->lgdc_ctxt_idx));
/* Checks for struct lustre_capa */
- LASSERTF((int)sizeof(struct lustre_capa) == 52, " found %llu\n",
+ LASSERTF((int)sizeof(struct lustre_capa) == 56, " found %llu\n",
(unsigned long long)(int)sizeof(struct lustre_capa));
LASSERTF((int)offsetof(struct lustre_capa, lc_uid) == 0, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_uid));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_uid) == 4, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_uid));
- LASSERTF((int)offsetof(struct lustre_capa, lc_op) == 4, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_op) == 8, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_op));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_op) == 4, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_op));
- LASSERTF((int)offsetof(struct lustre_capa, lc_ino) == 8, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_ino) == 12, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_ino));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_ino) == 8, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_ino));
- LASSERTF((int)offsetof(struct lustre_capa, lc_mdsid) == 16, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_mdsid) == 20, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_mdsid));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_mdsid) == 4, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_mdsid));
- LASSERTF((int)offsetof(struct lustre_capa, lc_keyid) == 20, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_keyid) == 24, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_keyid));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_keyid) == 4, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_keyid));
- LASSERTF((int)offsetof(struct lustre_capa, lc_expiry) == 24, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_expiry) == 28, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_expiry));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_expiry) == 8, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_expiry));
- LASSERTF((int)offsetof(struct lustre_capa, lc_flags) == 32, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_flags) == 36, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_flags));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_flags) == 4, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_flags));
- LASSERTF((int)offsetof(struct lustre_capa, lc_hmac) == 36, " found %llu\n",
+ LASSERTF((int)offsetof(struct lustre_capa, lc_hmac) == 40, " found %llu\n",
(unsigned long long)(int)offsetof(struct lustre_capa, lc_hmac));
LASSERTF((int)sizeof(((struct lustre_capa *)0)->lc_hmac) == 16, " found %llu\n",
(unsigned long long)(int)sizeof(((struct lustre_capa *)0)->lc_hmac));