* also round for short expiry, in case timer might miss.
* add mds_mfd_put() because mds_handle2mfd() will add ref.
* filter_verify_capa() logic error.
#define CAPA_HMAC_ALG "sha1"
/* capa ops */
-#define CAPA_READ MAY_READ /* 2 */
-#define CAPA_WRITE MAY_WRITE /* 4 */
+#define CAPA_WRITE MAY_WRITE /* 2 */
+#define CAPA_READ MAY_READ /* 4 */
#define CAPA_TRUNC 8
struct lustre_capa_data {
#define CAPA_EXPIRY (1UL << CAPA_EXPIRY_SHIFT)
#define CAPA_EXPIRY_MASK (~(CAPA_EXPIRY-1))
-#define CAPA_PRE_EXPIRY_NOROUND 3 /* sec */
+#define CAPA_PRE_EXPIRY_SHORT 3 /* sec */
#define CAPA_PRE_EXPIRY 300 /* sec */
/* struct lustre_capa.lc_flags */
-#define CAPA_FL_NOROUND 0x001 /* capa expiry not rounded */
+#define CAPA_FL_SHORT 0x001 /* short capa expiry */
#define CAPA_FL_REMUID 0x002 /* remote uid */
-#define CAPA_FL_TRUNC 0x004 /* truncate capa, this kind of capa won't be renewed */
static inline unsigned long capa_pre_expiry(struct lustre_capa *capa)
{
- return (capa->lc_flags & CAPA_FL_NOROUND) ?
- CAPA_PRE_EXPIRY_NOROUND : CAPA_PRE_EXPIRY;
+ return (capa->lc_flags & CAPA_FL_SHORT) ?
+ CAPA_PRE_EXPIRY_SHORT : CAPA_PRE_EXPIRY;
}
static inline __u64
round_expiry(__u32 timeout)
{
struct timeval tv;
+ int capa_expiry = CAPA_EXPIRY;
+ int mask = CAPA_EXPIRY_MASK;
__u64 expiry;
do_gettimeofday(&tv);
expiry = tv.tv_sec + timeout;
- if (timeout > CAPA_EXPIRY)
- expiry = (expiry + CAPA_EXPIRY - 1) & CAPA_EXPIRY_MASK;
+ if (timeout < CAPA_EXPIRY) {
+ capa_expiry = 64;
+ mask = ~63;
+ }
+
+ expiry = (expiry + capa_expiry - 1) & mask;
return expiry;
}
static inline int have_expired_capa(void)
{
struct obd_capa *ocapa;
+ struct lustre_capa *capa;
int expired = 0;
unsigned long expiry;
ENTRY;
spin_lock(&capa_lock);
if (!list_empty(ll_capa_list)) {
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);
+
+ if (!expired) {
+ capa = &ocapa->c_capa;
+ expiry = expiry_to_jiffies(capa->lc_expiry -
+ capa_pre_expiry(capa));
+ if (time_before(expiry, ll_capa_timer.expires) ||
+ !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);
int rc;
ENTRY;
- if (capa_expired(&ocapa->c_capa)) {
- /* this is the second time try to renew since the last
- * renewal failed, it means on one is openning it and
- * should be put now. */
- capa_put(ocapa);
- RETURN(0);
- }
+ if (capa_expired(&ocapa->c_capa))
+ RETURN(-ESTALE);
rc = md_getattr(md_exp, &lli->lli_id, valid, NULL, NULL, 0,
0, ocapa, &req);
{
struct thread_ctl *ctl = arg;
unsigned long flags;
+ int rc;
ENTRY;
{
while (1) {
struct l_wait_info lwi = { 0 };
- struct obd_capa *ocapa, *next = NULL, tcapa;
+ struct obd_capa *ocapa, *tmp, *next = NULL, tcapa;
unsigned long expiry, sleep = CAPA_PRE_EXPIRY;
l_wait_event(capa_thread.t_ctl_waitq,
break;
spin_lock(&capa_lock);
- list_for_each_entry(ocapa, ll_capa_list, c_list) {
+ list_for_each_entry_safe(ocapa, tmp, ll_capa_list, c_list) {
+ if (ocapa->c_capa.lc_flags & CAPA_FL_SHORT)
+ sleep = CAPA_PRE_EXPIRY_SHORT;
+
if (ocapa->c_capa.lc_op == CAPA_TRUNC)
continue;
tcapa = *ocapa;
spin_unlock(&capa_lock);
- ll_renew_capa(&tcapa);
+ rc = ll_renew_capa(&tcapa);
+ if (rc)
+ capa_put(ocapa);
spin_lock(&capa_lock);
} else {
break;
}
}
+
if (next) {
- 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;
+ struct lustre_capa *capa = &next->c_capa;
+
+ expiry = expiry_to_jiffies(capa->lc_expiry -
+ capa_pre_expiry(capa));
+ if (time_before(expiry, ll_capa_timer.expires) ||
+ !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);
ENTRY;
if (rc) {
- DEBUG_REQ(D_WARNING, req,
+ DEBUG_REQ(D_INFO, req,
"async getattr failed: rc = %d", rc);
RETURN(rc);
}
spin_lock(&capa_lock);
expiry = expiry_to_jiffies(capa->lc_expiry - capa_pre_expiry(capa));
+ CDEBUG(D_INFO, "expiry %lu vs timer %lu, base %p\n",
+ expiry, ll_capa_timer.expires, ll_capa_timer.base);
if (time_before(expiry, ll_capa_timer.expires) ||
!timer_pending(&ll_capa_timer)) {
mod_timer(&ll_capa_timer, expiry);
- CDEBUG(D_INFO, "ll_capa_timer new timer: %lu\n", expiry);
+ CDEBUG(D_INFO, "ll_capa_timer new expiry: %lu\n", expiry);
}
spin_unlock(&capa_lock);
mfd = mds_handle2mfd(&req_body->handle);
if (mfd == NULL) {
- DEBUG_CAPA(D_WARNING, req_capa, "no handle "LPX64" for",
+ DEBUG_CAPA(D_INFO, req_capa, "no handle "LPX64" for",
req_body->handle.cookie);
RETURN(-ESTALE);
}
mode);
RETURN(-EACCES);
}
+
+ mds_mfd_put(mfd);
}
LASSERT(repmsg->buflens[*offset] == sizeof(*capa));
capa->lc_keyid = le32_to_cpu(CUR_CAPA_KEY_ID(mds));
capa->lc_expiry = round_expiry(mds->mds_capa_timeout);
if (mds->mds_capa_timeout < CAPA_EXPIRY)
- capa->lc_flags |= CAPA_FL_NOROUND;
+ capa->lc_flags |= CAPA_FL_SHORT;
memcpy(key, CUR_CAPA_KEY(mds)->lk_key, sizeof(key));
spin_unlock(&mds_capa_lock);
int mds_close(struct ptlrpc_request *req, int offset);
int mds_done_writing(struct ptlrpc_request *req, int offset);
struct mds_file_data *mds_handle2mfd(struct lustre_handle *handle);
+void mds_mfd_put(struct mds_file_data *mfd);
int mds_validate_size(struct obd_device *obd, struct inode *inode,
struct mds_body *body, struct iattr *iattr);
int accmode(int flags);
RETURN(class_handle2object(handle->cookie));
}
-static void mds_mfd_put(struct mds_file_data *mfd)
+void mds_mfd_put(struct mds_file_data *mfd)
{
CDEBUG(D_INFO, "PUTting mfd %p : new refcount %d\n", mfd,
atomic_read(&mfd->mfd_refcount) - 1);
}
}
- list_add_tail(&ocapa->c_list, head);
+ list_add(&ocapa->c_list, head);
}
static inline void do_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
struct timeval tv;
do_gettimeofday(&tv);
- return (capa->lc_expiry < tv.tv_sec) ? 1 : 0;
+ return ((unsigned long )capa->lc_expiry <= tv.tv_sec) ? 1 : 0;
}
int __capa_is_to_expire(struct obd_capa *ocapa)
int pre_expiry = capa_pre_expiry(&ocapa->c_capa);
do_gettimeofday(&tv);
- return (ocapa->c_capa.lc_expiry - pre_expiry - 1 <= tv.tv_sec)? 1 : 0;
+ /* XXX: in case the lock is inaccurate, minus one more
+ * pre_expiry to make sure the expiry won't miss */
+ return ((unsigned long)ocapa->c_capa.lc_expiry -
+ 2 * pre_expiry <= tv.tv_sec)? 1 : 0;
}
int capa_is_to_expire(struct obd_capa *ocapa)
rc = memcmp(capa->lc_hmac, ocapa->c_bhmac,
sizeof(capa->lc_hmac));
} else {
- /* ocapa is obsolete */
- capa_put(ocapa);
- spin_unlock(&filter->fo_capa_lock);
+ /* ocapa is obsolete too */
+ ocapa->c_bvalid = 0;
+ goto new_capa;
+ }
+
+ if (rc && __capa_is_to_expire(ocapa)) {
+ /* client should use new expiry now */
+ ocapa->c_bvalid = 0;
goto new_capa;
}
spin_unlock(&filter->fo_capa_lock);
RETURN(rc ? -EACCES : 0);
}
-new_capa:
spin_lock(&filter->fo_capa_lock);
+new_capa:
list_for_each_entry(tmp, &filter->fo_capa_keys, k_list) {
if (tmp->k_key.lk_mdsid == capa->lc_mdsid) {
if (rkey == NULL)
spin_lock(&filter->fo_capa_lock);
memcpy(ocapa->c_bhmac, tcapa.lc_hmac, sizeof(ocapa->c_bhmac));
+ ocapa->c_bvalid = 1;
spin_unlock(&filter->fo_capa_lock);
}
goto verify;