Whamcloud - gitweb
- additional debug to catch the case when client gets openhandle w/o capa
[fs/lustre-release.git] / lustre / llite / llite_capa.c
index ee3585f..e9296b1 100644 (file)
@@ -43,21 +43,28 @@ static struct thread_ctl {
 static inline int have_expired_capa(void)
 {
         struct obd_capa *ocapa;
+        struct lustre_capa *capa;
         int expired = 0;
         unsigned long expiry;
+        struct timeval tv;
+
         ENTRY;
 
+        do_gettimeofday(&tv);
         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);
+                expired = __capa_is_to_expire(ocapa, &tv);
+                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);
@@ -77,16 +84,12 @@ static int ll_renew_capa(struct obd_capa *ocapa)
         struct inode *inode = ocapa->c_inode;
         struct obd_export *md_exp = ll_i2mdexp(inode);
         struct ll_inode_info *lli = ll_i2info(inode);
-        __u64 valid = 0;
+        __u64 valid = OBD_MD_CAPA;
         int rc;
         ENTRY;
 
-        valid |= OBD_MD_CAPA;
-
         rc = md_getattr(md_exp, &lli->lli_id, valid, NULL, NULL, 0,
                         0, ocapa, &req);
-        if (rc < 0)
-                CDEBUG(D_INFO, "md_getattr failed: rc = %d\n", rc);
         RETURN(rc);
 }
 
@@ -94,6 +97,7 @@ static int ll_capa_thread(void *arg)
 {
         struct thread_ctl *ctl = arg;
         unsigned long flags;
+        int rc;
         ENTRY;
 
         {
@@ -116,40 +120,67 @@ static int ll_capa_thread(void *arg)
 
         while (1) {
                 struct l_wait_info lwi = { 0 };
-                struct obd_capa *ocapa, *next = NULL;
+                struct obd_capa *ocapa, tcapa, *tmp, *next = NULL;
                 unsigned long expiry, sleep = CAPA_PRE_EXPIRY;
+                struct inode *inode;
+                struct timeval tv;
 
                 l_wait_event(capa_thread.t_ctl_waitq,
                              (have_expired_capa() || ll_capa_check_stop()),
                              &lwi);
 
+                if (ll_capa_check_stop())
+                        break;
+
+                do_gettimeofday(&tv);
                 spin_lock(&capa_lock);
-                list_for_each_entry(ocapa, ll_capa_list, c_list) {
-                        if (__capa_is_to_expire(ocapa)) {
-                                /* get capa in case it's deleted */
-                                __capa_get(ocapa);
+                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;
+
+                        if (capa_expired(&ocapa->c_capa)) {
+                                capa_put_nolock(ocapa);
+                                continue;
+                        }
 
+                        if (__capa_is_to_expire(ocapa, &tv)) {
+                                inode = igrab(ocapa->c_inode);
+                                if (inode == NULL) {
+                                        DEBUG_CAPA(D_ERROR, &ocapa->c_capa,
+                                                   "igrab failed for");
+                                        continue;
+                                }
+
+                                tcapa = *ocapa;
                                 spin_unlock(&capa_lock);
-                                ll_renew_capa(ocapa);
-                                capa_put(ocapa, CLIENT_CAPA);
+
+                                rc = ll_renew_capa(&tcapa);
+                                iput(inode);
+
                                 spin_lock(&capa_lock);
                         } else {
                                 next = ocapa;
                                 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);
 
-                if (ll_capa_check_stop())
-                        break;
-
                 /* wait ll_renew_capa finish */
                 set_current_state(TASK_INTERRUPTIBLE);
                 schedule_timeout(sleep * HZ);
@@ -205,32 +236,57 @@ void ll_capa_thread_stop(void)
         EXIT;
 }
 
-int ll_set_och_capa(struct inode *inode, struct lookup_intent *it,
-                   struct obd_client_handle *och)
+int ll_set_capa(struct inode *inode, struct lookup_intent *it,
+                struct obd_client_handle *och)
 {
         struct ptlrpc_request *req = LUSTRE_IT(it)->it_data;
-        struct ll_inode_info *lli = ll_i2info(inode);
         struct mds_body *body;
         struct lustre_capa *capa;
-        __u64 mdsid = lli->lli_id.li_fid.lf_group;
-        unsigned long ino = lli->lli_id.li_stc.u.e3s.l3s_ino;
-        int capa_op = (it->it_flags & MAY_WRITE) ? MAY_WRITE : MAY_READ;
+        struct obd_capa *ocapa;
+        struct ll_inode_info *lli = ll_i2info(inode);
         unsigned long expiry;
-        int rc = 0;
-        ENTRY;
+
+        if (!S_ISREG(inode->i_mode))
+                return 0;
+
+        /* GNS code path will have no req */
+        if (!req)
+                return 0;
 
         body = lustre_msg_buf(req->rq_repmsg, 1, sizeof (*body));
         LASSERT(body != NULL);          /* reply already checked out */
         LASSERT_REPSWABBED(req, 1);     /* and swabbed down */
 
+        if (!(body->valid & OBD_MD_CAPA)) {
+                if (atomic_read(&ll_capa_stat))
+                        DEBUG_REQ(D_ERROR, req,
+                                  "no capa for (uid %u, op %d, "DLID4"\n",
+                                   (unsigned)current->uid, it->it_flags,
+                                   OLID4(&lli->lli_id));
+
+                return 0;
+        }
+
+        ENTRY;
+
         capa = lustre_msg_buf(req->rq_repmsg, 7, sizeof (*capa));
         LASSERT(capa != NULL);          /* reply already checked out */
         LASSERT_REPSWABBED(req, 7);     /* and swabbed down */
 
-        och->och_capa = capa_get(current->uid, capa_op, mdsid, ino,
-                                 CLIENT_CAPA, capa, inode, &body->handle);
-        if (!och->och_capa)
-                rc = -ENOMEM;
+        ocapa = capa_renew(capa, CLIENT_CAPA);
+        if (!ocapa)
+                RETURN(-ENOMEM);
+
+        spin_lock(&capa_lock);
+        ocapa->c_inode = inode;
+        ocapa->c_handle = och->och_fh;
+        spin_unlock(&capa_lock);
+
+        spin_lock(&lli->lli_lock);
+        /* in case it was linked to lli_capas already */
+        if (list_empty(&ocapa->c_lli_list))
+                list_add(&ocapa->c_lli_list, &lli->lli_capas);
+        spin_unlock(&lli->lli_lock);
 
         expiry = expiry_to_jiffies(capa->lc_expiry - capa_pre_expiry(capa));
 
@@ -242,6 +298,64 @@ int ll_set_och_capa(struct inode *inode, struct lookup_intent *it,
         }
         spin_unlock(&capa_lock);
 
-        RETURN(rc);
+        RETURN(0);
+}
+
+int ll_set_trunc_capa(struct ptlrpc_request *req, int offset, struct inode *inode)
+{
+        struct mds_body *body;
+        struct obd_capa *ocapa;
+        struct lustre_capa *capa;
+        struct ll_inode_info *lli = ll_i2info(inode);
+
+        body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body));
+        if (!body)
+                return -ENOMEM;
+
+        if (!(body->valid & OBD_MD_CAPA))
+                return 0;
+
+        ENTRY;
+        capa = (struct lustre_capa *)lustre_swab_repbuf(req, offset + 1,
+                                        sizeof(*capa), lustre_swab_lustre_capa);
+        if (!capa)
+                RETURN(-ENOMEM);        
+
+        ocapa = capa_renew(capa, CLIENT_CAPA);
+        if (!ocapa)
+                RETURN(-ENOMEM);
+
+        spin_lock(&lli->lli_lock);
+        /* in case it was linked to lli_capas already */
+        if (list_empty(&ocapa->c_lli_list))
+                list_add(&ocapa->c_lli_list, &lli->lli_capas);
+        spin_unlock(&lli->lli_lock);
+
+        RETURN(0);
 }
 
+struct obd_capa *ll_get_capa(struct inode *inode, uid_t uid, int op)
+{
+        struct ll_inode_info *lli = ll_i2info(inode);
+        struct obd_capa *ocapa, *tmp;
+        ENTRY;
+
+        list_for_each_entry_safe(ocapa, tmp, &lli->lli_capas, c_lli_list) {
+                if (ocapa->c_capa.lc_ruid != uid)
+                        continue;
+                if (ocapa->c_capa.lc_op != op)
+                        continue;
+
+                RETURN(ocapa);
+        }
+
+        if (atomic_read(&ll_capa_stat)) {
+                CDEBUG(D_ERROR, "can't find capa for (uid %u, op %d, mdsid "
+                       LPU64", ino %u igen %u) failed.\n",
+                       (unsigned)uid, op, id_group(&lli->lli_id),
+                       (unsigned)id_ino(&lli->lli_id), id_gen(&lli->lli_id));
+                atomic_set(&ll_capa_stat, 0);
+        }
+        
+        RETURN(NULL);
+}