Whamcloud - gitweb
Land b1_2 onto HEAD (20040304_171022)
[fs/lustre-release.git] / lustre / llite / file.c
index bac31cb..2cbc22e 100644 (file)
@@ -318,64 +318,68 @@ static int ll_lock_to_stripe_offset(struct inode *inode, struct ldlm_lock *lock)
  *
  * No one can dirty the extent until we've finished our work and they can
  * enqueue another lock.  The DLM protects us from ll_file_read/write here,
- * but other kernel actors could have pages locked. */
+ * but other kernel actors could have pages locked.
+ *
+ * Called with the DLM lock held. */
 void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
                               struct ldlm_lock *lock, __u32 stripe)
 {
-        struct ldlm_extent *extent = &lock->l_policy_data.l_extent;
+        ldlm_policy_data_t tmpex;
         unsigned long start, end, count, skip, i, j;
         struct page *page;
-        int rc, discard = lock->l_flags & LDLM_FL_DISCARD_DATA;
+        int rc, rc2, discard = lock->l_flags & LDLM_FL_DISCARD_DATA;
+        struct lustre_handle lockh;
         ENTRY;
 
-        CDEBUG(D_INODE, "obdo %lu inode %p ["LPU64"->"LPU64"] size: %llu\n",
-               inode->i_ino, inode, extent->start, extent->end, inode->i_size);
+        memcpy(&tmpex, &lock->l_policy_data, sizeof(tmpex));
+        CDEBUG(D_INODE|D_PAGE, "inode %lu(%p) ["LPU64"->"LPU64"] size: %llu\n",
+               inode->i_ino, inode, tmpex.l_extent.start, tmpex.l_extent.end,
+               inode->i_size);
 
         /* our locks are page granular thanks to osc_enqueue, we invalidate the
          * whole page. */
-        LASSERT((extent->start & ~PAGE_CACHE_MASK) == 0);
-        LASSERT(((extent->end+1) & ~PAGE_CACHE_MASK) == 0);
+        LASSERT((tmpex.l_extent.start & ~PAGE_CACHE_MASK) == 0);
+        LASSERT(((tmpex.l_extent.end + 1) & ~PAGE_CACHE_MASK) == 0);
 
-        start = extent->start >> PAGE_CACHE_SHIFT;
         count = ~0;
         skip = 0;
-        end = (extent->end >> PAGE_CACHE_SHIFT) + 1;
-        if ((end << PAGE_CACHE_SHIFT) < extent->end)
-                end = ~0;
+        start = tmpex.l_extent.start >> PAGE_CACHE_SHIFT;
+        end = tmpex.l_extent.end >> PAGE_CACHE_SHIFT;
         if (lsm->lsm_stripe_count > 1) {
                 count = lsm->lsm_stripe_size >> PAGE_CACHE_SHIFT;
                 skip = (lsm->lsm_stripe_count - 1) * count;
-                start += (start/count * skip) + (stripe * count);
+                start += start/count * skip + stripe * count;
                 if (end != ~0)
-                        end += (end/count * skip) + (stripe * count);
-        } 
+                        end += end/count * skip + stripe * count;
+        }
+        if (end < tmpex.l_extent.end >> PAGE_CACHE_SHIFT)
+                end = ~0;
 
         i = (inode->i_size + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
         if (i < end)
                 end = i;
 
-        CDEBUG(D_INODE, "walking page indices start: %lu j: %lu count: %lu "
-               "skip: %lu end: %lu%s\n", start, start % count, count, skip, end,
-               discard ? " (DISCARDING)" : "");
+        CDEBUG(D_INODE|D_PAGE, "walking page indices start: %lu j: %lu "
+               "count: %lu skip: %lu end: %lu%s\n", start, start % count,
+               count, skip, end, discard ? " (DISCARDING)" : "");
 
         /* this is the simplistic implementation of page eviction at
          * cancelation.  It is careful to get races with other page
          * lockers handled correctly.  fixes from bug 20 will make it
          * more efficient by associating locks with pages and with
          * batching writeback under the lock explicitly. */
-        for (i = start, j = start % count ; ; j++, i++) {
-                if (j == count) {
-                        i += skip;
-                        j = 0;
-                }
-                if (i >= end)
-                        break;
+        for (i = start, j = start % count ; i <= end;
+             j++, i++, tmpex.l_extent.start += PAGE_CACHE_SIZE) {
+                LASSERTF(tmpex.l_extent.start< lock->l_policy_data.l_extent.end,
+                         LPU64" >= "LPU64" start %lu i %lu end %lu\n",
+                         tmpex.l_extent.start, lock->l_policy_data.l_extent.end,
+                         start, i, end);
 
                 ll_pgcache_lock(inode->i_mapping);
                 if (list_empty(&inode->i_mapping->dirty_pages) &&
                     list_empty(&inode->i_mapping->clean_pages) &&
                     list_empty(&inode->i_mapping->locked_pages)) {
-                        CDEBUG(D_INODE, "nothing left\n");
+                        CDEBUG(D_INODE|D_PAGE, "nothing left\n");
                         ll_pgcache_unlock(inode->i_mapping);
                         break;
                 }
@@ -385,14 +389,14 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
 
                 page = find_get_page(inode->i_mapping, i);
                 if (page == NULL)
-                        continue;
-                LL_CDEBUG_PAGE(page, "locking page\n");
+                        goto next_index;
+                LL_CDEBUG_PAGE(D_PAGE, page, "locking page\n");
                 lock_page(page);
 
                 /* page->mapping to check with racing against teardown */
                 if (page->mapping && PageDirty(page) && !discard) {
                         ClearPageDirty(page);
-                        LL_CDEBUG_PAGE(page, "found dirty\n");
+                        LL_CDEBUG_PAGE(D_PAGE, page, "found dirty\n");
                         ll_pgcache_lock(inode->i_mapping);
                         list_del(&page->list);
                         list_add(&page->list, &inode->i_mapping->locked_pages);
@@ -407,13 +411,26 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
                         lock_page(page);
                 }
 
-                /* checking again to account for writeback's lock_page() */
-                if (page->mapping != NULL) {
-                        LL_CDEBUG_PAGE(page, "truncating\n");
+                tmpex.l_extent.end = tmpex.l_extent.start + PAGE_CACHE_SIZE - 1;
+                /* check to see if another DLM lock covers this page */
+                rc2 = ldlm_lock_match(lock->l_resource->lr_namespace,
+                                      LDLM_FL_BLOCK_GRANTED|LDLM_FL_CBPENDING |
+                                      LDLM_FL_TEST_LOCK,
+                                      &lock->l_resource->lr_name, LDLM_EXTENT,
+                                      &tmpex, LCK_PR | LCK_PW, &lockh);
+                if (rc2 == 0 && page->mapping != NULL) {
+                        // checking again to account for writeback's lock_page()
+                        LL_CDEBUG_PAGE(D_PAGE, page, "truncating\n");
                         ll_truncate_complete_page(page);
                 }
                 unlock_page(page);
                 page_cache_release(page);
+
+        next_index:
+                if (j == count) {
+                        i += skip;
+                        j = 0;
+                }
         }
         EXIT;
 }
@@ -439,12 +456,17 @@ static int ll_extent_lock_callback(struct ldlm_lock *lock,
                         CERROR("ldlm_cli_cancel failed: %d\n", rc);
                 break;
         case LDLM_CB_CANCELING: {
-                struct inode *inode = ll_inode_from_lock(lock);
+                struct inode *inode;
                 struct ll_inode_info *lli;
                 struct lov_stripe_md *lsm;
                 __u32 stripe;
                 __u64 kms;
 
+                /* This lock wasn't granted, don't try to evict pages */
+                if (lock->l_req_mode != lock->l_granted_mode)
+                        RETURN(0);
+
+                inode = ll_inode_from_lock(lock);
                 if (inode == NULL)
                         RETURN(0);
                 lli = ll_i2info(inode);
@@ -569,7 +591,7 @@ static int ll_glimpse_callback(struct ldlm_lock *lock, void *reqp)
                 LBUG();
         }
 
-        LDLM_DEBUG(lock, "i_size: %Lu -> stripe number %d -> size %Lu",
+        LDLM_DEBUG(lock, "i_size: %llu -> stripe number %u -> size "LPU64,
                    inode->i_size, data.stripe_number, data.size);
 
         rc = lustre_pack_reply(req, 1, &size, NULL);
@@ -607,8 +629,10 @@ int ll_glimpse_size(struct inode *inode, struct ost_lvb *lvb)
                          LCK_PR, &flags, ll_extent_lock_callback,
                          ldlm_completion_ast, ll_glimpse_callback, inode,
                          sizeof(*lvb), lustre_swab_ost_lvb, &lockh);
-        if (rc > 0)
+        if (rc > 0) {
+                CERROR("obd_enqueue returned rc %d, returning -EIO\n", rc);
                 RETURN(-EIO);
+        }
 
         lvb->lvb_size = lov_merge_size(lli->lli_smd, 0);
         //inode->i_mtime = lov_merge_mtime(lli->lli_smd, inode->i_mtime);
@@ -720,8 +744,8 @@ static ssize_t ll_file_read(struct file *filp, char *buf, size_t count,
                 inode->i_size = kms;
         }
 
-        CDEBUG(D_INFO, "Reading inode %lu, "LPSZ" bytes, offset %Ld, i_size "
-               LPU64"\n", inode->i_ino, count, *ppos, inode->i_size);
+        CDEBUG(D_INFO, "Read ino %lu, "LPSZ" bytes, offset %lld, i_size %llu\n",
+               inode->i_ino, count, *ppos, inode->i_size);
 
         /* turn off the kernel's read-ahead */
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
@@ -1224,6 +1248,7 @@ static int ll_have_md_lock(struct dentry *de)
 
         CDEBUG(D_INFO, "trying to match res "LPU64"\n", res_id.name[0]);
 
+        /* FIXME use LDLM_FL_TEST_LOCK instead */
         flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING;
         if (ldlm_lock_match(obddev->obd_namespace, flags, &res_id, LDLM_PLAIN,
                             NULL, LCK_PR, &lockh)) {