* Added a acquire_unreferenced_ref() to vm_store

* his has to be used by the page writer to make sure the vnode is still valid.
* This should have been the final nail on the Luposian bug - I haven't tested
  it yet, but we'll certainly see :-)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22462 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2007-10-06 15:35:38 +00:00
parent 80f5469291
commit c950f17a51
7 changed files with 41 additions and 13 deletions

View File

@ -219,19 +219,20 @@ struct vm_store {
};
typedef struct vm_store_ops {
void (*destroy)(struct vm_store *backing_store);
status_t (*commit)(struct vm_store *backing_store, off_t size);
bool (*has_page)(struct vm_store *backing_store, off_t offset);
status_t (*read)(struct vm_store *backing_store, off_t offset,
void (*destroy)(struct vm_store *backingStore);
status_t (*commit)(struct vm_store *backingStore, off_t size);
bool (*has_page)(struct vm_store *backingStore, off_t offset);
status_t (*read)(struct vm_store *backingStore, off_t offset,
const iovec *vecs, size_t count, size_t *_numBytes, bool mayBlock,
bool fsReenter);
status_t (*write)(struct vm_store *backing_store, off_t offset,
status_t (*write)(struct vm_store *backingStore, off_t offset,
const iovec *vecs, size_t count, size_t *_numBytes, bool mayBlock,
bool fsReenter);
status_t (*fault)(struct vm_store *backing_store,
status_t (*fault)(struct vm_store *backingStore,
struct vm_address_space *aspace, off_t offset);
void (*acquire_ref)(struct vm_store *backing_store);
void (*release_ref)(struct vm_store *backing_store);
status_t (*acquire_unreferenced_ref)(struct vm_store *backingStore);
void (*acquire_ref)(struct vm_store *backingStore);
void (*release_ref)(struct vm_store *backingStore);
} vm_store_ops;
#endif /* _KERNEL_VM_TYPES_H */

View File

@ -83,6 +83,15 @@ store_write(struct vm_store *_store, off_t offset, const iovec *vecs,
}
static status_t
store_acquire_unreferenced_ref(struct vm_store *_store)
{
vnode_store *store = (vnode_store *)_store;
struct vnode *vnode;
return vfs_get_vnode(store->device, store->inode, &vnode);
}
static void
store_acquire_ref(struct vm_store *_store)
{
@ -106,6 +115,7 @@ static vm_store_ops sStoreOps = {
&store_read,
&store_write,
NULL, /* fault */
&store_acquire_unreferenced_ref,
&store_acquire_ref,
&store_release_ref
};
@ -128,6 +138,7 @@ vm_create_vnode_store(struct vnode *vnode)
store->vnode = vnode;
store->file_cache_ref = NULL;
vfs_vnode_to_node_ref(vnode, &store->device, &store->inode);
return &store->vm;
}

View File

@ -12,6 +12,8 @@
struct vnode_store {
vm_store vm;
struct vnode* vnode;
dev_t device;
ino_t inode;
void* file_cache_ref;
};

View File

@ -665,6 +665,15 @@ page_writer(void* /*unused*/)
if (!cacheLocker.IsLocked())
continue;
vm_cache *cache = page->cache;
if (cache->store->ops->acquire_unreferenced_ref != NULL) {
// we need our own reference to the store, as it might
// currently be destructed
if (cache->store->ops->acquire_unreferenced_ref(cache->store)
!= B_OK)
continue;
}
locker.Lock();
remove_page_from_queue(&sModifiedPageQueue, page);
page->state = PAGE_STATE_BUSY;
@ -675,7 +684,7 @@ page_writer(void* /*unused*/)
//dprintf("write page %p, cache %p (%ld)\n", page, page->cache, page->cache->ref_count);
vm_clear_map_flags(page, PAGE_MODIFIED);
vm_cache_acquire_ref(page->cache);
vm_cache_acquire_ref(cache);
pages[numPages++] = page;
}
@ -711,6 +720,8 @@ page_writer(void* /*unused*/)
busyConditions[i].Unpublish();
mutex_unlock(&cache->lock);
if (cache->store->ops->release_ref != NULL)
cache->store->ops->release_ref(cache->store);
vm_cache_release_ref(cache);
}
}

View File

@ -154,6 +154,7 @@ static vm_store_ops anonymous_ops = {
&anonymous_read,
&anonymous_write,
&anonymous_fault,
NULL, // acquire unreferenced ref
NULL, // acquire ref
NULL // release ref
};

View File

@ -78,8 +78,9 @@ static vm_store_ops device_ops = {
&device_read,
&device_write,
&device_fault,
NULL,
NULL
NULL, // acquire unreferenced ref
NULL, // acquire ref
NULL // release ref
};

View File

@ -67,8 +67,9 @@ static vm_store_ops null_ops = {
&null_read,
&null_write,
&null_fault,
NULL,
NULL
NULL, // acquire unreferenced ref
NULL, // acquire ref
NULL // release ref
};