operations do from file->f_dentry->d_inode directly.
* all dir capabilities should always renew because ll_revalid_it needs
parent dir capability.
* filter update capability key more intelligently.
* rename ll_i2mdscapa -> ll_mdscapa_get, ll_lookup_oss_capa -> ll_osscapa_get.
* other code cleanup.
}
static int cml_capa_get(const struct lu_env *env, struct md_object *mo,
- struct lustre_capa *capa)
+ struct lustre_capa *capa, int renewal)
{
int rc;
ENTRY;
- rc = mo_capa_get(env, md_object_next(mo), capa);
+ rc = mo_capa_get(env, md_object_next(mo), capa, renewal);
RETURN(rc);
}
}
static int cmr_capa_get(const struct lu_env *env, struct md_object *mo,
- struct lustre_capa *capa)
+ struct lustre_capa *capa, int renewal)
{
RETURN(-EFAULT);
}
struct dt_object *dt, const struct lu_rdpg *rdpg,
struct lustre_capa *capa);
struct obd_capa *(*do_capa_get)(const struct lu_env *env,
- struct dt_object *dt, __u64 opc);
+ struct dt_object *dt,
+ struct lustre_capa *old, __u64 opc);
};
/*
/* lustre_capa.lc_opc */
enum {
- /* MDS only fid capability */
CAPA_OPC_BODY_WRITE = 1<<0, /* write fid data */
CAPA_OPC_BODY_READ = 1<<1, /* read fid data */
CAPA_OPC_INDEX_LOOKUP = 1<<2, /* lookup fid */
CAPA_OPC_INDEX_INSERT = 1<<3, /* insert fid */
CAPA_OPC_INDEX_DELETE = 1<<4, /* delete fid */
- /* OSS only fid capability */
CAPA_OPC_OSS_WRITE = 1<<5, /* write oss object data */
CAPA_OPC_OSS_READ = 1<<6, /* read oss object data */
CAPA_OPC_OSS_TRUNC = 1<<7, /* truncate oss object */
- /* MDS & OSS both might have */
CAPA_OPC_META_WRITE = 1<<8, /* write fid meta data */
CAPA_OPC_META_READ = 1<<9, /* read fid meta data */
};
-#define CAPA_OPC_MDS_ONLY \
- (CAPA_OPC_BODY_WRITE | CAPA_OPC_BODY_READ | \
- CAPA_OPC_INDEX_LOOKUP | CAPA_OPC_INDEX_INSERT | CAPA_OPC_INDEX_DELETE)
-#define CAPA_OPC_OSS_ONLY \
+#define CAPA_OPC_MDS_ONLY \
+ (CAPA_OPC_BODY_WRITE | CAPA_OPC_BODY_READ | CAPA_OPC_INDEX_LOOKUP | \
+ CAPA_OPC_INDEX_INSERT | CAPA_OPC_INDEX_DELETE)
+#define CAPA_OPC_OSS_ONLY \
(CAPA_OPC_OSS_WRITE | CAPA_OPC_OSS_READ | CAPA_OPC_OSS_TRUNC)
#define CAPA_OPC_MDS_DEFAULT ~CAPA_OPC_OSS_ONLY
#define CAPA_OPC_OSS_DEFAULT ~(CAPA_OPC_MDS_ONLY | CAPA_OPC_OSS_ONLY)
struct client_capa {
struct inode *inode;
struct list_head lli_list; /* link to lli_oss_capas */
- atomic_t open_count; /* open count */
};
struct target_capa {
- struct hlist_node c_hash; /* link to capa hash */
+ struct hlist_node c_hash; /* link to capa hash */
};
struct obd_capa {
* to OSS before capability expires.
*/
return ocapa->c_expiry -
- ((ocapa->c_capa.lc_flags & CAPA_FL_SHORT_EXPIRY) ? 40:1200) * HZ;
+ ((ocapa->c_capa.lc_flags & CAPA_FL_SHORT_EXPIRY) ? 300:1200) * HZ;
}
#ifdef __KERNEL__
int (*moo_close)(const struct lu_env *env, struct md_object *obj,
struct md_attr *ma);
int (*moo_capa_get)(const struct lu_env *, struct md_object *,
- struct lustre_capa *);
+ struct lustre_capa *, int renewal);
};
/*
static inline int mo_capa_get(const struct lu_env *env,
struct md_object *m,
- struct lustre_capa *c)
+ struct lustre_capa *c,
+ int renewal)
{
LASSERT(m->mo_ops->moo_capa_get);
- return m->mo_ops->moo_capa_get(env, m, c);
+ return m->mo_ops->moo_capa_get(env, m, c, renewal);
}
static inline int mdo_lookup(const struct lu_env *env,
unlock_kernel();
handle = (flag) ? &ldd->lld_mnt_och : &ldd->lld_cwd_och;
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = obd_pin(sbi->ll_md_exp, ll_inode2fid(inode), oc, handle, flag);
capa_put(oc);
if (rc) {
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) off %lu\n",
inode->i_ino, inode->i_generation, inode, (unsigned long)hash);
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_readpage(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode),
oc, hash, page, &request);
capa_put(oc);
GOTO(out, rc = -EINVAL);
}
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode), oc,
filename, namelen, OBD_MD_FLID, 0,
&request);
if (IS_ERR(filename))
RETURN(PTR_ERR(filename));
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getattr_name(sbi->ll_md_exp,
ll_inode2fid(inode), oc,
filename, strlen(filename) + 1,
GOTO(out_name, rc);
}
} else {
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
OBD_MD_FLEASIZE | OBD_MD_FLDIREA,
lmmsize, &request);
((struct ll_iattr *)&op_data->attr)->ia_attr_flags = inode->i_flags;
op_data->ioepoch = ll_i2info(inode)->lli_ioepoch;
memcpy(&op_data->handle, fh, sizeof(op_data->handle));
- op_data->mod_capa1 = ll_i2mdscapa(inode);
+ op_data->mod_capa1 = ll_mdscapa_get(inode);
}
static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
LUSTRE_FPRIVATE(file) = NULL;
ll_file_data_put(fd);
- ll_oss_capa_close(inode, file);
+ ll_capa_close(inode);
RETURN(rc);
}
if (!S_ISREG(inode->i_mode))
GOTO(out, rc);
- ll_oss_capa_open(inode, file);
+ ll_capa_open(inode);
lsm = lli->lli_smd;
if (lsm == NULL) {
OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
OBD_MD_FLBLKSZ | OBD_MD_FLMTIME |
OBD_MD_FLCTIME | OBD_MD_FLGROUP;
- oinfo.oi_capa = ll_i2mdscapa(inode);
+ oinfo.oi_capa = ll_mdscapa_get(inode);
set = ptlrpc_prep_set();
if (set == NULL) {
rc = err;
}
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
err = md_sync(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
&req);
capa_put(oc);
OBD_MD_FLMTIME | OBD_MD_FLCTIME |
OBD_MD_FLGROUP);
- ocapa = ll_lookup_oss_capa(inode, CAPA_OPC_OSS_WRITE);
+ ocapa = ll_osscapa_get(inode, CAPA_OPC_OSS_WRITE);
err = obd_sync(ll_i2sbi(inode)->ll_dt_exp, oa, lsm,
0, OBD_OBJECT_EOF, ocapa);
capa_put(ocapa);
RETURN(rc);
valid |= OBD_MD_FLEASIZE | OBD_MD_FLMODEASIZE;
}
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid,
ealen, &req);
capa_put(oc);
list_add(&ocapa->c_list, before ?: head);
}
-static int inode_have_md_lock(struct inode *inode, __u64 inodebits)
+static inline int obd_capa_open_count(struct obd_capa *oc)
{
- struct obd_export *exp = ll_i2mdexp(inode);
- ldlm_policy_data_t policy = { .l_inodebits = {inodebits}};
- struct lustre_handle lockh;
- int flags = LDLM_FL_BLOCK_GRANTED|LDLM_FL_CBPENDING|LDLM_FL_TEST_LOCK;
- int rc;
- ENTRY;
-
- rc = md_lock_match(exp, flags, ll_inode2fid(inode),
- LDLM_IBITS, &policy, LCK_CR|LCK_CW|LCK_PR, &lockh);
- RETURN(rc);
+ struct ll_inode_info *lli = ll_i2info(oc->u.cli.inode);
+ return atomic_read(&lli->lli_open_count);
}
static void ll_delete_capa(struct obd_capa *ocapa)
struct ll_inode_info *lli = ll_i2info(ocapa->u.cli.inode);
if (capa_for_mds(&ocapa->c_capa)) {
- capa_put(ocapa);
LASSERT(lli->lli_mds_capa == ocapa);
lli->lli_mds_capa = NULL;
} else if (capa_for_oss(&ocapa->c_capa)) {
free_capa(ocapa);
}
+static void inline assert_expired_capa(struct obd_capa *oc)
+{
+ if (S_ISDIR(oc->u.cli.inode->i_mode))
+ DEBUG_CAPA(D_ERROR, &oc->c_capa, "shouldn't release dir");
+ else if (obd_capa_open_count(oc))
+ DEBUG_CAPA(D_ERROR, &oc->c_capa, "shouldn't release opened");
+ else if (obd_capa_is_root(oc))
+ DEBUG_CAPA(D_ERROR, &oc->c_capa, "shouldn't release root");
+ else
+ return;
+ LBUG();
+}
+
/* three places where client capa is deleted:
* 1. capa_thread_main(), main place to delete expired capa.
* 2. ll_clear_inode_capas() in ll_clear_inode().
}
if (capa_for_mds(&ocapa->c_capa) &&
+ !S_ISDIR(ocapa->u.cli.inode->i_mode) &&
+ obd_capa_open_count(ocapa) == 0 &&
+ !obd_capa_is_root(ocapa) &&
!ll_have_md_lock(ocapa->u.cli.inode,
- MDS_INODELOCK_LOOKUP) &&
- !obd_capa_is_root(ocapa)) {
- /* MDS capa without LOOKUP lock won't renew,
+ MDS_INODELOCK_LOOKUP)) {
+ assert_expired_capa(ocapa);
+ /* MDS capa without LOOKUP lock, and the related
+ * inode is not opened, it won't renew,
* move to idle list (except root fid) */
DEBUG_CAPA(D_SEC, &ocapa->c_capa,
"skip renewal for");
}
if (capa_for_oss(&ocapa->c_capa) &&
- atomic_read(&ocapa->u.cli.open_count) == 0) {
- /* oss capa with open_count == 0 won't renew,
+ obd_capa_open_count(ocapa) == 0) {
+ assert_expired_capa(ocapa);
+ /* oss capa with open count == 0 won't renew,
* move to idle list */
list_del_init(&ocapa->c_list);
sort_add_capa(ocapa, &ll_idle_capas);
rc = md_renew_capa(ll_i2mdexp(inode), ocapa,
ll_update_capa);
spin_lock(&capa_lock);
- if (rc)
+ if (rc) {
+ DEBUG_CAPA(D_ERROR, &ocapa->c_capa,
+ "renew failed: %d", rc);
sort_add_capa(ocapa, &ll_idle_capas);
+ }
}
if (next)
update_capa_timer(next, capa_renewal_time(next));
list_for_each_entry_safe(ocapa, tmp, &ll_idle_capas, c_list) {
- LASSERT(atomic_read(&ocapa->u.cli.open_count) == 0);
-
if (!capa_is_expired(ocapa)) {
if (!next)
update_capa_timer(ocapa, ocapa->c_expiry);
return NULL;
}
-struct obd_capa *ll_lookup_oss_capa(struct inode *inode, __u64 opc)
+struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc)
{
struct ll_inode_info *lli = ll_i2info(inode);
struct obd_capa *ocapa;
RETURN(ocapa);
}
-struct obd_capa *ll_i2mdscapa(struct inode *inode)
+struct obd_capa *ll_mdscapa_get(struct inode *inode)
{
struct ll_inode_info *lli = ll_i2info(inode);
struct obd_capa *ocapa;
spin_unlock(&capa_lock);
if (ocapa && !obd_capa_is_valid(ocapa)) {
- DEBUG_CAPA(D_ERROR, &ocapa->c_capa, "invalid");
+ DEBUG_CAPA(D_ERROR, &ocapa->c_capa, "invalid (flags %d)",
+ ocapa->c_flags);
capa_put(ocapa);
ocapa = NULL;
}
CDEBUG(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ?
D_ERROR : D_SEC, "no MDS capability for fid "DFID"\n",
PFID(ll_inode2fid(inode)));
- if (inode_have_md_lock(inode, MDS_INODELOCK_LOOKUP))
- LBUG();
+#if 0
+ LASSERT(!S_ISDIR(inode->i_mode));
+ LASSERT(!obd_capa_open_count(ocapa));
+ LASSERT(!ll_have_md_lock(ocapa->u.cli.inode,
+ MDS_INODELOCK_LOOKUP));
+#endif
atomic_set(&ll_capa_debug, 0);
}
if (!old) {
ocapa->u.cli.inode = inode;
- lli->lli_mds_capa = capa_get(ocapa);
+ lli->lli_mds_capa = ocapa;
obd_capa_clear_new(ocapa);
obd_capa_set_valid(ocapa);
old = do_lookup_oss_capa(inode, capa->lc_opc & CAPA_OPC_OSS_ONLY);
if (!old) {
ocapa->u.cli.inode = inode;
- atomic_set(&ocapa->u.cli.open_count, 0);
INIT_LIST_HEAD(&ocapa->u.cli.lli_list);
obd_capa_set_valid(ocapa);
int rc;
spin_lock(&capa_lock);
- rc = capa_for_mds(&ocapa->c_capa) ? do_add_mds_capa(inode, pcapa) :
- do_add_oss_capa(inode, pcapa);
+ rc = capa_for_mds(&ocapa->c_capa) ? do_add_mds_capa(inode, pcapa) :
+ do_add_oss_capa(inode, pcapa);
ocapa = *pcapa;
/* truncate capa won't renew, or no existed capa changed, don't update
/* failed capa won't be renewed any longer, but if -EIO, client
* might be doing recovery, retry in 1 min. */
spin_lock(&capa_lock);
- if (rc == -EIO) {
- expiry = cfs_time_current() + cfs_time_seconds(60);
+ if (rc == -EIO && !capa_is_expired(ocapa)) {
+ expiry = jiffies + 60 * HZ;
DEBUG_CAPA(D_SEC, &ocapa->c_capa,
"renewal failed: -EIO, retry in 1 min");
goto retry;
return rc;
}
-void ll_oss_capa_open(struct inode *inode, struct file *file)
+void ll_capa_open(struct inode *inode)
{
- struct obd_capa *ocapa;
- int opc = capa_open_opc(open_flags_to_accmode(file->f_flags));
+ struct ll_inode_info *lli = ll_i2info(inode);
- if ((ll_i2sbi(inode)->ll_flags & LL_SBI_OSS_CAPA) == 0)
+ if ((ll_i2sbi(inode)->ll_flags & (LL_SBI_MDS_CAPA | LL_SBI_OSS_CAPA))
+ == 0)
return;
if (!S_ISREG(inode->i_mode))
return;
- spin_lock(&capa_lock);
- ocapa = do_lookup_oss_capa(inode, opc);
- if (!ocapa) {
- if (atomic_read(&ll_capa_debug)) {
- CDEBUG(D_ERROR, "no opc %x capability for fid "DFID"\n",
- opc, PFID(ll_inode2fid(inode)));
- atomic_set(&ll_capa_debug, 0);
- }
- spin_unlock(&capa_lock);
- return;
- }
- atomic_inc(&ocapa->u.cli.open_count);
- spin_unlock(&capa_lock);
-
- DEBUG_CAPA(D_SEC, &ocapa->c_capa, "open (count: %d)",
- atomic_read(&ocapa->u.cli.open_count));
+ atomic_inc(&lli->lli_open_count);
}
-void ll_oss_capa_close(struct inode *inode, struct file *file)
+void ll_capa_close(struct inode *inode)
{
- struct obd_capa *ocapa;
- int opc = capa_open_opc(open_flags_to_accmode(file->f_flags));
+ struct ll_inode_info *lli = ll_i2info(inode);
- if ((ll_i2sbi(inode)->ll_flags & LL_SBI_OSS_CAPA) == 0)
+ if ((ll_i2sbi(inode)->ll_flags & (LL_SBI_MDS_CAPA | LL_SBI_OSS_CAPA))
+ == 0)
return;
if (!S_ISREG(inode->i_mode))
return;
- spin_lock(&capa_lock);
- ocapa = do_lookup_oss_capa(inode, opc);
- if (!ocapa) {
- spin_unlock(&capa_lock);
- return;
- }
- atomic_dec(&ocapa->u.cli.open_count);
- spin_unlock(&capa_lock);
-
- DEBUG_CAPA(D_SEC, &ocapa->c_capa, "close (count: %d)",
- atomic_read(&ocapa->u.cli.open_count));
+ atomic_dec(&lli->lli_open_count);
}
/* delete CAPA_OPC_OSS_TRUNC only */
struct lov_stripe_md *lli_smd;
/* fid capability */
+ /* open count currently used by capability only, indicate whether
+ * capability needs renewal */
+ atomic_t lli_open_count;
struct obd_capa *lli_mds_capa;
- /* oss capability list */
struct list_head lli_oss_capas;
};
int ll_capa_thread_start(void);
void ll_capa_thread_stop(void);
void ll_capa_timer_callback(unsigned long unused);
-struct obd_capa *ll_lookup_oss_capa(struct inode *inode, __u64 opc);
+
struct obd_capa *ll_add_capa(struct inode *inode, struct obd_capa *ocapa);
-void ll_oss_capa_open(struct inode *inode, struct file *file);
-void ll_oss_capa_close(struct inode *inode, struct file *file);
int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa);
+
+void ll_capa_open(struct inode *inode);
+void ll_capa_close(struct inode *inode);
+
+struct obd_capa *ll_mdscapa_get(struct inode *inode);
+struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc);
+
void ll_truncate_free_capa(struct obd_capa *ocapa);
void ll_clear_inode_capas(struct inode *inode);
-struct obd_capa *ll_i2mdscapa(struct inode *inode);
#endif /* LLITE_INTERNAL_H */
lli->lli_open_fd_read_count = lli->lli_open_fd_write_count = 0;
lli->lli_open_fd_exec_count = 0;
INIT_LIST_HEAD(&lli->lli_dead_list);
- INIT_LIST_HEAD(&lli->lli_oss_capas);
lli->lli_remote_perms = NULL;
sema_init(&lli->lli_rmtperm_sem, 1);
+ INIT_LIST_HEAD(&lli->lli_oss_capas);
}
/* COMPAT_146 */
oinfo.oi_oa = oa;
oinfo.oi_md = lsm;
- oinfo.oi_capa = ll_i2mdscapa(inode);
+ oinfo.oi_capa = ll_mdscapa_get(inode);
/* XXX: this looks unnecessary now. */
rc = obd_setattr_rqset(sbi->ll_dt_exp, &oinfo, NULL);
struct mdt_body *body;
struct obd_capa *oc;
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
OBD_MD_FLFLAGS, 0, &req);
capa_put(oc);
ll_i2gids(op_data->suppgids, i1, i2);
op_data->fid1 = ll_i2info(i1)->lli_fid;
- op_data->mod_capa1 = ll_i2mdscapa(i1);
+ op_data->mod_capa1 = ll_mdscapa_get(i1);
/* @i2 may be NULL. In this case caller itself has to initialize ->fid2
* if needed. */
if (i2) {
op_data->fid2 = *ll_inode2fid(i2);
- op_data->mod_capa2 = ll_i2mdscapa(i2);
+ op_data->mod_capa2 = ll_mdscapa_get(i2);
}
op_data->name = name;
if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len))
GOTO(out, rc = -EFAULT);
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getxattr(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
OBD_MD_FLXATTR, XATTR_NAME_LUSTRE_ACL, cmd,
ioc->cmd_len, ioc->res_len, 0, &req);
if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len))
GOTO(out, rc = -EFAULT);
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_setxattr(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
OBD_MD_FLXATTR, XATTR_NAME_LUSTRE_ACL, cmd,
ioc->cmd_len, ioc->res_len, 0, &req);
{
struct inode *inode = de->d_inode;
struct lu_fid *fid = ll_inode2fid(inode);
- struct obd_capa *ocapa = ll_i2mdscapa(inode);
+ struct obd_capa *ocapa = ll_mdscapa_get(inode);
int len = (sizeof(*fid) + sizeof(struct lustre_capa) + 3)/4;
char *p = (char *)fh;
sbi = ll_s2sbi(dir->i_sb);
- oc = ll_i2mdscapa(dir);
+ oc = ll_mdscapa_get(dir);
rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(dir), oc,
dotdot, strlen(dotdot) + 1, 0, 0, &req);
if (rc) {
LBUG();
}
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_get_remote_perm(sbi->ll_md_exp, ll_inode2fid(inode), oc, &req);
capa_put(oc);
if (rc) {
/* NB partial write, so we might not have CAPA_OPC_OSS_READ capa */
opc = cmd & OBD_BRW_WRITE ? CAPA_OPC_OSS_WRITE :
CAPA_OPC_OSS_WRITE | CAPA_OPC_OSS_READ;
- oinfo.oi_capa = ll_lookup_oss_capa(inode, opc);
+ oinfo.oi_capa = ll_osscapa_get(inode, opc);
rc = obd_brw(cmd, ll_i2dtexp(inode), &oinfo, 1, &pg, NULL);
capa_put(oinfo.oi_capa);
if (rc == 0)
ll_inode_size_unlock(inode, 0);
- oinfo.oi_capa = ll_lookup_oss_capa(inode, CAPA_OPC_OSS_TRUNC);
+ oinfo.oi_capa = ll_osscapa_get(inode, CAPA_OPC_OSS_TRUNC);
rc = obd_punch_rqset(ll_i2dtexp(inode), &oinfo, NULL);
ll_truncate_free_capa(oinfo.oi_capa);
if (rc)
int opc = cmd & OBD_BRW_WRITE ? CAPA_OPC_OSS_WRITE :
CAPA_OPC_OSS_WRITE | CAPA_OPC_OSS_READ;
- return ll_lookup_oss_capa(llap->llap_page->mapping->host, opc);
+ return ll_osscapa_get(llap->llap_page->mapping->host, opc);
}
static struct obd_async_page_ops ll_async_page_ops = {
LPROC_LL_DIRECT_READ, size);
opc = CAPA_OPC_OSS_READ | CAPA_OPC_OSS_WRITE;
}
- ocapa = ll_lookup_oss_capa(inode, opc);
+ ocapa = ll_osscapa_get(inode, opc);
rc = obd_brw_rqset(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
ll_i2dtexp(inode), &oa, lsm, page_count, pga, NULL,
ocapa);
RETURN(0);
}
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
OBD_MD_LINKNAME, symlen, request);
capa_put(oc);
if (xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0)
RETURN(0);
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
value, size, 0, flags, &req);
capa_put(oc);
#endif
do_getxattr:
- oc = ll_i2mdscapa(inode);
+ oc = ll_mdscapa_get(inode);
rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
NULL, 0, size, 0, &req);
capa_put(oc);
req->rq_oi.oi_policy.l_extent.end = re;
req->rq_oi.oi_policy.l_extent.gid = -1;
- req->rq_oi.oi_capa = oinfo->oi_capa;
-
lov_set_add_req(req, set);
}
if (!set->set_count)
struct lustre_capa *capa;
ENTRY;
- if (status)
- DEBUG_CAPA(D_ERROR, &oc->c_capa, "renew failed: %d for",
- status);
+ if (status) {
+ DEBUG_CAPA(status == -ENOENT ? D_SEC : D_ERROR, &oc->c_capa,
+ "renew failed: %d for", status);
+ GOTO(out, capa = ERR_PTR(status));
+ }
body = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*body),
lustre_swab_mdt_body);
}
static int mdd_capa_get(const struct lu_env *env, struct md_object *obj,
- struct lustre_capa *capa)
+ struct lustre_capa *capa, int renewal)
{
struct dt_object *next;
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct obd_capa *oc;
+ int rc = 0;
ENTRY;
LASSERT(lu_object_exists(mdd2lu_obj(mdd_obj)));
next = mdd_object_child(mdd_obj);
- oc = next->do_ops->do_capa_get(env, next, capa->lc_opc);
- if (oc) {
+ oc = next->do_ops->do_capa_get(env, next, renewal ? capa : NULL,
+ capa->lc_opc);
+ if (IS_ERR(oc)) {
+ rc = PTR_ERR(oc);
+ } else {
capa_cpy(capa, oc);
capa_put(oc);
}
- RETURN(0);
+ RETURN(rc);
}
struct md_device_operations mdd_ops = {
oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
oinfo->oi_oa = oa;
oinfo->oi_md = lsm;
- oinfo->oi_capa = next->do_ops->do_capa_get(env, next,
+ oinfo->oi_capa = next->do_ops->do_capa_get(env, next, NULL,
CAPA_OPC_MDS_DEFAULT);
rc = obd_setattr(lov_exp, oinfo, oti);
if (rc)
RETURN(rc);
- oc = next->do_ops->do_capa_get(env, next, CAPA_OPC_MDS_DEFAULT);
+ oc = next->do_ops->do_capa_get(env, next, NULL, CAPA_OPC_MDS_DEFAULT);
rc = mds_osc_setattr_async(obd, tmp_la->la_uid, tmp_la->la_gid, lmm,
lmm_size, NULL, seq, oid, oc);
capa_put(oc);
{
struct mdt_device *mdt = args;
struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
- struct lustre_capa_key *tmp, *key = &mdt->mdt_capa_keys[1];
+ struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0],
+ *rkey = &mdt->mdt_capa_keys[1];
+ struct lustre_capa_key *tmp;
struct lu_env env;
struct mdt_thread_info *info;
struct md_device *next;
if (time_after(mdt->mdt_ck_expiry, jiffies))
break;
- *tmp = *key;
- make_capa_key(tmp, mdsnum, key->lk_keyid);
+ *tmp = *rkey;
+ make_capa_key(tmp, mdsnum, rkey->lk_keyid);
next = mdt->mdt_child;
rc = next->md_ops->mdo_update_capa_key(&env, next, tmp);
if (!rc) {
+ spin_lock(&capa_lock);
+ *bkey = *rkey;
+ *rkey = *tmp;
+ spin_unlock(&capa_lock);
+
rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys);
- if (!rc) {
+ if (rc) {
spin_lock(&capa_lock);
- mdt->mdt_capa_keys[0] = *key;
- *key = *tmp;
+ *rkey = *bkey;
+ memset(bkey, 0, sizeof(*bkey));
spin_unlock(&capa_lock);
-
+ } else {
set_capa_key_expiry(mdt);
-
- DEBUG_CAPA_KEY(D_SEC, key, "new");
+ DEBUG_CAPA_KEY(D_SEC, rkey, "new");
}
}
if (rc) {
- DEBUG_CAPA_KEY(D_ERROR, key, "update failed for");
+ DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for");
/* next retry is in 300 sec */
mdt->mdt_ck_expiry = jiffies + 300 * HZ;
}
LASSERT(capa);
capa->lc_opc = CAPA_OPC_MDS_DEFAULT;
- rc = mo_capa_get(info->mti_env, mdt_object_child(root), capa);
+ rc = mo_capa_get(info->mti_env, mdt_object_child(root), capa,
+ 0);
mdt_object_put(info->mti_env, root);
if (rc == 0)
body->valid |= OBD_MD_FLMDSCAPA;
capa = req_capsule_server_get(&info->mti_pill, &RMF_CAPA1);
LASSERT(capa);
capa->lc_opc = CAPA_OPC_MDS_DEFAULT;
- rc = mo_capa_get(env, next, capa);
+ rc = mo_capa_get(env, next, capa, 0);
if (rc)
RETURN(rc);
repbody->valid |= OBD_MD_FLMDSCAPA;
int rc;
ENTRY;
+ /* NB: see mdt_unpack_req_pack_rep */
+ if (!obj)
+ GOTO(out, rc = -ENOENT);
+
body = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
LASSERT(body);
c = req_capsule_client_get(&info->mti_pill, &RMF_CAPA1);
LASSERT(c);
- if ((capa_for_mds(c) && !mdt->mdt_opts.mo_mds_capa) ||
- (capa_for_oss(c) && !mdt->mdt_opts.mo_oss_capa)) {
+ if (!mdt->mdt_opts.mo_mds_capa) {
DEBUG_CAPA(D_SEC, c,
"mds has disabled capability, skip renew for");
GOTO(out, rc = -ENOENT);
LASSERT(capa);
*capa = *c;
- capa->lc_expiry = 0;
- rc = mo_capa_get(info->mti_env, mdt_object_child(obj), capa);
+ rc = mo_capa_get(info->mti_env, mdt_object_child(obj), capa, 1);
+ if (rc)
+ GOTO(out, rc);
body->valid |= OBD_MD_FLOSSCAPA;
EXIT;
int rc;
ENTRY;
- LASSERT(obj != NULL);
- LASSERT(lu_object_assert_exists(&obj->mot_obj.mo_lu));
-
reqbody = req_capsule_client_get(&info->mti_pill, &RMF_MDT_BODY);
if (reqbody == NULL)
GOTO(out, rc = -EFAULT);
RETURN(rc);
}
+ LASSERT(obj != NULL);
+ LASSERT(lu_object_assert_exists(&obj->mot_obj.mo_lu));
+
if (reqbody->valid & OBD_MD_FLRMTPERM) {
rc = mdt_init_ucred(info, reqbody);
if (rc)
if ((flags & HABEO_CORPUS) &&
!mdt_object_exists(obj)) {
mdt_object_put(env, obj);
- rc = -ENOENT;
+#if 0
+ /* for capability renew ENOENT will be handled in
+ * mdt_renew_capa */
+ if (body->valid & OBD_MD_FLOSSCAPA)
+ rc = 0;
+ else
+#endif
+ rc = -ENOENT;
} else {
info->mti_object = obj;
rc = 0;
}
}
- /* capability setting changed by /proc, needs reinitialize ctxt */
+ /* capability setting changed via /proc, needs reinitialize ctxt */
if (info->mti_mdt && info->mti_mdt->mdt_capa_conf) {
mdt_init_capa_ctxt(info->mti_env, info->mti_mdt);
info->mti_mdt->mdt_capa_conf = 0;
spin_lock_init(&m->mdt_ioepoch_lock);
m->mdt_opts.mo_compat_resname = 0;
- m->mdt_capa_timeout = CAPA_TIMEOUT;
+ m->mdt_capa_timeout = 320; // CAPA_TIMEOUT;
m->mdt_capa_alg = CAPA_HMAC_ALG_SHA1;
m->mdt_ck_timeout = CAPA_KEY_TIMEOUT;
obd->obd_replayable = 1;
GOTO(err_free_ns, rc);
}
- rc = mdt_ck_thread_start(m);
- if (rc)
- GOTO(err_free_ns, rc);
m->mdt_ck_timer.function = mdt_ck_timer_callback;
m->mdt_ck_timer.data = (unsigned long)m;
init_timer(&m->mdt_ck_timer);
+ rc = mdt_ck_thread_start(m);
+ if (rc)
+ GOTO(err_free_ns, rc);
rc = mdt_start_ptlrpc_service(m);
if (rc)
capa = req_capsule_server_get(&info->mti_pill, &RMF_CAPA1);
LASSERT(capa);
capa->lc_opc = CAPA_OPC_MDS_DEFAULT;
- rc = mo_capa_get(info->mti_env, mdt_object_child(o), capa);
+ rc = mo_capa_get(info->mti_env, mdt_object_child(o), capa, 0);
if (rc)
RETURN(rc);
repbody->valid |= OBD_MD_FLMDSCAPA;
capa = req_capsule_server_get(&info->mti_pill, &RMF_CAPA2);
LASSERT(capa);
capa->lc_opc = CAPA_OPC_OSS_DEFAULT | capa_open_opc(flags);
- rc = mo_capa_get(info->mti_env, mdt_object_child(o), capa);
+ rc = mo_capa_get(info->mti_env, mdt_object_child(o), capa, 0);
if (rc)
RETURN(rc);
repbody->valid |= OBD_MD_FLOSSCAPA;
if (mdt->mdt_opts.mo_oss_capa &&
S_ISREG(lu_object_attr(&mo->mot_obj.mo_lu))) {
+ /* FIXME: only sent truncate capability back in size change
+ * case */
struct lustre_capa *capa;
capa = req_capsule_server_get(&info->mti_pill, &RMF_CAPA1);
LASSERT(capa);
capa->lc_opc = CAPA_OPC_OSS_DEFAULT | CAPA_OPC_OSS_TRUNC;
- rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa);
+ rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0);
if (rc)
RETURN(rc);
repbody->valid |= OBD_MD_FLOSSCAPA;
{
struct hlist_node *pos;
struct obd_capa *ocapa;
- int len = offsetof(struct lustre_capa, lc_hmac);
-
- /* MDS get capa case */
- if (capa->lc_expiry == 0)
- len = offsetof(struct lustre_capa, lc_keyid);
+ int len = capa->lc_expiry ? sizeof(*capa) :
+ offsetof(struct lustre_capa, lc_keyid);
hlist_for_each_entry(ocapa, pos, head, u.tgt.c_hash) {
if (memcmp(&ocapa->c_capa, capa, len))
return key->k_key.lk_keyid;
}
-int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *key)
+int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *new)
{
struct filter_obd *filter = &obd->u.filter;
- struct filter_capa_key *k, *rkey = NULL, *bkey = NULL;
+ struct filter_capa_key *k, *keys[2] = { NULL, NULL };
+ int i;
spin_lock(&capa_lock);
list_for_each_entry(k, &filter->fo_capa_keys, k_list) {
- if (k->k_key.lk_mdsid != key->lk_mdsid)
+ if (k->k_key.lk_mdsid != new->lk_mdsid)
continue;
- if (rkey)
- bkey = k;
- else
- rkey = k;
+ if (keys[0]) {
+ keys[1] = k;
+ if (filter_ck_keyid(keys[1]) > filter_ck_keyid(keys[0]))
+ keys[1] = keys[0], keys[0] = k;
+ } else {
+ keys[0] = k;
+ }
}
spin_unlock(&capa_lock);
- if (rkey && bkey && filter_ck_keyid(rkey) < filter_ck_keyid(bkey)) {
- k = rkey;
- rkey = bkey;
- bkey = k;
+ for (i = 0; i < 2; i++) {
+ if (!keys[i])
+ continue;
+ if (filter_ck_keyid(keys[i]) != new->lk_keyid)
+ continue;
+ /* maybe because of recovery or other reasons, MDS sent the
+ * the old capability key again.
+ */
+ spin_lock(&capa_lock);
+ keys[i]->k_key = *new;
+ spin_unlock(&capa_lock);
+
+ RETURN(0);
}
- if (bkey) {
- k = bkey;
+ if (keys[1]) {
+ /* if OSS already have two keys, update the old one */
+ k = keys[1];
} else {
OBD_ALLOC_PTR(k);
if (!k)
}
spin_lock(&capa_lock);
- k->k_key = *key;
+ k->k_key = *new;
if (list_empty(&k->k_list))
list_add(&k->k_list, &filter->fo_capa_keys);
spin_unlock(&capa_lock);
- DEBUG_CAPA_KEY(D_SEC, key, "new");
+ DEBUG_CAPA_KEY(D_SEC, new, "new");
RETURN(0);
}
RETURN(-EINVAL);
}
- if (capa)
- size[REQ_REC_OFF + 1] = sizeof(struct lustre_capa);
+ size[REQ_REC_OFF + 1] = capa ? sizeof(struct lustre_capa) : 0;
req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OST_VERSION,
OST_SYNC, 3, size, NULL);
{
struct osd_thread_info *oti;
struct obd_capa *oc;
- int i, rc = 1;
+ int i, rc = 0;
ENTRY;
oti = lu_context_key_get(&env->le_ctx, &osd_key);
oc = capa_lookup(capa);
if (oc) {
- if (memcmp(&oc->c_capa, capa, sizeof(*capa))) {
- DEBUG_CAPA(D_ERROR, capa, "HMAC mismatch");
- rc = -EACCES;
- } else if (capa_is_expired(oc)) {
+ if (capa_is_expired(oc)) {
DEBUG_CAPA(D_ERROR, capa, "expired");
rc = -ESTALE;
}
RETURN(-ESTALE);
}
- rc = capa_hmac(oti->oti_capa_hmac, capa, oti->oti_capa_key.lk_key);
+ rc = capa_hmac(oti->oti_capa.lc_hmac, capa, oti->oti_capa_key.lk_key);
if (rc)
RETURN(rc);
- if (memcmp(oti->oti_capa_hmac, capa->lc_hmac, sizeof(capa->lc_hmac))) {
+ if (memcmp(oti->oti_capa.lc_hmac, capa->lc_hmac, sizeof(capa->lc_hmac)))
+ {
DEBUG_CAPA(D_ERROR, capa, "HMAC mismatch");
RETURN(-EACCES);
}
oc = capa_add(capa);
capa_put(oc);
- RETURN(1);
+ RETURN(0);
}
static int osd_object_auth(const struct lu_env *env, struct dt_object *dt,
{
const struct lu_fid *fid = lu_object_fid(&dt->do_lu);
struct osd_device *dev = osd_dev(dt->do_lu.lo_dev);
+ int rc;
if (!dev->od_fl_capa)
return 0;
return -EACCES;
}
- if (!capa_is_sane(env, capa, dev->od_capa_keys)) {
- DEBUG_CAPA(D_ERROR, capa, "insane");
+ if ((rc = capa_is_sane(env, capa, dev->od_capa_keys))) {
+ DEBUG_CAPA(D_ERROR, capa, "insane (rc %d)", rc);
return -EACCES;
}
static struct obd_capa *osd_capa_get(const struct lu_env *env,
struct dt_object *dt,
+ struct lustre_capa *old,
__u64 opc)
{
struct osd_thread_info *info = lu_context_key_get(&env->le_ctx,
ENTRY;
if (!dev->od_fl_capa)
- RETURN(NULL);
+ RETURN(ERR_PTR(-ENOENT));
LASSERT(dt_object_exists(dt));
LASSERT(osd_invariant(obj));
+ /* renewal sanity check */
+ if (old && osd_object_auth(env, dt, old, opc))
+ RETURN(ERR_PTR(-EACCES));
+
capa->lc_fid = *fid;
capa->lc_opc = opc;
capa->lc_flags |= dev->od_capa_alg << 24;
if (dev->od_capa_timeout < CAPA_TIMEOUT)
capa->lc_flags |= CAPA_FL_SHORT_EXPIRY;
+ capa->lc_expiry = 0; /* this is flag to get a not-expired one */
oc = capa_lookup(capa);
if (oc) {
rc = capa_hmac(capa->lc_hmac, capa, key->lk_key);
if (rc) {
DEBUG_CAPA(D_ERROR, capa, "HMAC failed: %d for", rc);
- RETURN(NULL);
+ RETURN(ERR_PTR(rc));
}
oc = capa_add(capa);
/*
*XXX temporary: for capa operations.
*/
- char oti_capa_hmac[CAPA_HMAC_KEY_MAX_LEN];
struct lustre_capa_key oti_capa_key;
struct lustre_capa oti_capa;
};