/* } pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ }; */
} pupd_prm = {40, 500, 64, 256, 10*HZ, 30*HZ, 5*HZ };
+#if 0
+static void obdfs_lock_page(struct page *page)
+{
+ while (TryLockPage(page))
+ ___wait_on_page(page);
+}
+#endif
static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
int nr_slots, struct page **pages, char **bufs,
*flag = OBD_BRW_CREATE;
tmp = page_list;
- while ( (tmp = tmp->next) != page_list && (num < nr_slots) ) {
+ while ( ((tmp = tmp->next) != page_list) && (num < nr_slots) ) {
struct obdfs_pgrq *req;
struct page *page;
req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
page = req->rq_page;
+
if (check_time &&
(jiffies - req->rq_jiffies) < pupd_prm.age_buffer)
continue;
* Note that obdfs_pgrq_del() also deletes the request.
*/
obdfs_pgrq_del(req);
-
+ /*
+ obdfs_lock_page(page);
+ */
if ( !page ) {
CDEBUG(D_INODE, "no page \n");
continue;
}
- CDEBUG(D_INODE, "adding page %p to vector\n", page);
bufs[num] = (char *)page_address(page);
pages[num] = page;
counts[num] = PAGE_SIZE;
offsets[num] = ((obd_off)page->index) << PAGE_SHIFT;
+ CDEBUG(D_INODE, "ENQ inode %ld, page %p addr %p to vector\n",
+ inode->i_ino, page, (char *)page_address(page));
num++;
}
return num;
}
+/* dequeue requests for a dying inode */
+void obdfs_dequeue_reqs(struct inode *inode)
+{
+
+ struct list_head *tmp;
+
+ tmp = obdfs_islist(inode);
+ if ( list_empty(tmp) ) {
+ EXIT;
+ return;
+ }
+
+ /* take it out of the super list */
+ list_del(tmp);
+ INIT_LIST_HEAD(obdfs_islist(inode));
+
+ tmp = obdfs_iplist(inode);
+ while ( (tmp = tmp->next) != obdfs_iplist(inode) ) {
+ struct obdfs_pgrq *req;
+ struct page *page;
+
+ req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
+ page = req->rq_page;
+ /* take it out of the list and free */
+ obdfs_pgrq_del(req);
+ /* now put the page away */
+ put_page(page);
+ }
+
+}
+
/* Remove writeback requests for the superblock */
-int obdfs_flush_reqs(struct list_head *inode_list, int flush_inode,
- int check_time)
+int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
{
struct list_head *tmp = inode_list;
int total_io = 0;
&counts[num_io],
&offsets[num_io],
&flags[num_obdos],1);
+ CDEBUG(D_INODE, "FLUSHED inode %ld, pages flushed: %d\n",
+ inode->i_ino, res);
if ( res < 0 ) {
err = res;
goto ERR;
} /* obdfs_remove_pages_from_cache */
-static void obdfs_flush_dirty_pages(int check_time)
+void obdfs_flush_dirty_pages(int check_time)
{
struct list_head *sl;
list_entry(sl, struct obdfs_sb_info, osi_list);
/* walk write requests here, use the sb, check the time */
- obdfs_flush_reqs(&sbi->osi_inodes, 0, 1);
+ obdfs_flush_reqs(&sbi->osi_inodes, 0);
}
-#if 0
- /* again, but now we wait for completion */
- sl = &obdfs_super_list;
- while ( (sl = sl->next) != &obdfs_super_list ) {
- struct obdfs_sb_info *sbi =
- list_entry(sl, struct obdfs_sb_info, sl_chain);
-
- /* walk write requests here */
- obdfs_flush_reqs(&sbi->osi_pages, 0, check_time);
- }
-#endif
}
else
{
stop_pupdate:
+ obdfs_flush_dirty_pages(0);
tsk->state = TASK_STOPPED;
/* MOD_DEC_USE_COUNT; */
printk("pupdated stopped...\n");
}
/* asynchronous setattr etc for the future ... */
/* flush_inodes(); */
- obdfs_flush_dirty_pages(1);
+ obdfs_flush_dirty_pages(1);
}
}
/* XXX need to do something like this here:
send_sig(SIGTERM, current, 0);
*/
- 1;
+ 1;
+ /*obdfs_flush_dirty_pages(0); */
}
/* not reached */
int obdfs_flush_reqs(struct list_head *page_list,
int flush_inode, int check_time);
+void obdfs_flush_dirty_pages(int check_time);
/* SYNCHRONOUS I/O for an inode */
static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
} /* obdfs_readpage */
static kmem_cache_t *obdfs_pgrq_cachep = NULL;
+static int obdfs_cache_count = 0;
int obdfs_init_pgrqcache(void)
{
inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
{
- CDEBUG(D_INODE, "deleting page %p from list\n", pgrq->rq_page);
+ obdfs_cache_count--;
+ CDEBUG(D_INODE, "deleting page %p from list [count %d]\n", pgrq->rq_page, obdfs_cache_count);
list_del(&pgrq->rq_plist);
kmem_cache_free(obdfs_pgrq_cachep, pgrq);
}
{
ENTRY;
if (obdfs_pgrq_cachep != NULL) {
- CDEBUG(D_INODE, "destroying obdfs_pgrqcache at %p\n",
- obdfs_pgrq_cachep);
+ CDEBUG(D_INODE, "destroying obdfs_pgrqcache at %p, count %d\n",
+ obdfs_pgrq_cachep, obdfs_cache_count);
if (kmem_cache_destroy(obdfs_pgrq_cachep))
printk(KERN_INFO "obd_cleanup_pgrqcache: unable to free all of cache\n");
} else
} /* obdfs_find_in_page_list */
+static struct page*
+obdfs_find_page_index(struct inode *inode, unsigned long index)
+{
+ struct list_head *page_list = obdfs_iplist(inode);
+ struct list_head *tmp;
+ struct page *page;
+
+ ENTRY;
+
+ CDEBUG(D_INODE, "looking for inode %ld pageindex %ld\n", inode->i_ino, index);
+ OIDEBUG(inode);
+
+ if (list_empty(page_list)) {
+ EXIT;
+ return NULL;
+ }
+ tmp = page_list;
+ while ( (tmp = tmp->next) != page_list ) {
+ struct obdfs_pgrq *pgrq;
+
+ pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
+ page = pgrq->rq_page;
+ if (index == page->index) {
+ CDEBUG(D_INODE, "INDEX SEARC found page %p in list, index %ld\n", page, index);
+ EXIT;
+ return page;
+ }
+ }
+
+ EXIT;
+ return NULL;
+} /* obdfs_find_in_page_list */
+
+
/* call and free pages from Linux page cache */
int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
obd_count num_obdos, struct obdo **obdos,
/* release the pages from the page cache */
while ( num_io > 0 ) {
num_io--;
- CDEBUG(D_INODE, "calling put_page for %p\n", pages[num_io]);
+ CDEBUG(D_INODE, "calling put_page for %p, index %ld\n", pages[num_io], pages[num_io]->index);
+ /*
+ UnlockPage(pages[num_io]);
+ */
put_page(pages[num_io]);
}
*/
static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
{
- struct obdfs_pgrq *pgrq;
+ int res = 0;
ENTRY;
- pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
- CDEBUG(D_INODE, "adding inode %ld page %p, pgrq: %p\n",
- inode->i_ino, page, pgrq);
- if (!pgrq) {
- EXIT;
- return -ENOMEM;
- }
- memset(pgrq, 0, sizeof(*pgrq));
-
- pgrq->rq_page = page;
-
- get_page(pgrq->rq_page);
/* If this page isn't already in the inode page list, add it */
if ( !obdfs_find_in_page_list(inode, page) ) {
- CDEBUG(D_INODE, "adding page %p to inode list %p\n", page,
- obdfs_iplist(inode));
+ struct obdfs_pgrq *pgrq;
+ pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
+ CDEBUG(D_INODE, "adding inode %ld page %p, pgrq: %p, cache count [%d]\n",
+ inode->i_ino, page, pgrq, obdfs_cache_count);
+ if (!pgrq) {
+ EXIT;
+ return -ENOMEM;
+ }
+ memset(pgrq, 0, sizeof(*pgrq));
+
+ pgrq->rq_page = page;
+ get_page(pgrq->rq_page);
list_add(&pgrq->rq_plist, obdfs_iplist(inode));
}
/* If inode isn't already on the superblock inodes list, add it */
if ( list_empty(obdfs_islist(inode)) ) {
- CDEBUG(D_INODE, "adding inode %p to superblock list %p\n",
- obdfs_islist(inode), obdfs_slist(inode));
+ CDEBUG(D_INODE, "adding inode %ld to superblock list %p\n",
+ inode->i_ino, obdfs_slist(inode));
list_add(obdfs_islist(inode), obdfs_slist(inode));
}
- EXIT;
/* XXX For testing purposes, we write out the page here.
* In the future, a flush daemon will write out the page.
- return obdfs_flush_reqs(obdfs_slist(inode), 0, 0);
+ res = obdfs_flush_reqs(obdfs_slist(inode), 0);
+ obdfs_flush_dirty_pages(1);
*/
- return 0;
+
+ EXIT;
+ return res;
+ /*return 0;*/
} /* obdfs_add_page_to_cache */
int err;
ENTRY;
- PDEBUG(page, "WRITEPAGE");
+ /* PDEBUG(page, "WRITEPAGE"); */
if ( sync )
err = obdfs_brw(WRITE, inode, page, 1);
- else
+ else {
err = obdfs_add_page_to_cache(inode, page);
+ CDEBUG(D_IOCTL, "DO_WR ino: %ld, page %p, err %d, uptodata %d\n", inode->i_ino, page, err, Page_Uptodate(page));
+ }
if ( !err )
SetPageUptodate(page);
- PDEBUG(page,"WRITEPAGE");
+ /* PDEBUG(page,"WRITEPAGE"); */
EXIT;
return err;
} /* obdfs_do_writepage */
return page;
}
+
+ if ( obdfs_find_page_index(inode, offset) ) {
+ printk("OVERWRITE: found dirty page %p, index %ld\n", page, page->index);
+ }
+
err = obdfs_brw(READ, inode, page, create);
if ( err ) {