#define MAX_ERRNO 1000L
#endif
-#define LockPage(pp) lock_page(pp)
-#define UnlockPage(pp) unlock_page(pp)
extern struct backing_dev_info afs_backing_dev_info;
extern struct vcache *afs_globalVp;
struct AFS_FLOCK flock;
/* Convert to a lock format afs_lockctl understands. */
- memset((char *)&flock, 0, sizeof(flock));
+ memset(&flock, 0, sizeof(flock));
flock.l_type = flp->fl_type;
flock.l_pid = flp->fl_pid;
flock.l_whence = 0;
cred_t *credp = crref();
struct AFS_FLOCK flock;
/* Convert to a lock format afs_lockctl understands. */
- memset((char *)&flock, 0, sizeof(flock));
+ memset(&flock, 0, sizeof(flock));
flock.l_type = flp->fl_type;
flock.l_pid = flp->fl_pid;
flock.l_whence = 0;
SetPageUptodate(page);
if (task)
- UnlockPage(page);
+ unlock_page(page);
} else if (task) {
afs_pagecopy_queue_page(task, cachepage, page);
} else {
}
if (code && task) {
- UnlockPage(page);
+ unlock_page(page);
}
out:
isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
if(pp->index > isize) {
if(PageLocked(pp))
- UnlockPage(pp);
+ unlock_page(pp);
continue;
}
code = add_to_page_cache(pp, mapping, pp->index, GFP_KERNEL);
if(base_index != pp->index) {
if(PageLocked(pp))
- UnlockPage(pp);
+ unlock_page(pp);
page_cache_release(pp);
iovecp[page_ix].iov_base = (void *) 0;
base_index++;
base_index++;
if(code) {
if(PageLocked(pp))
- UnlockPage(pp);
+ unlock_page(pp);
page_cache_release(pp);
iovecp[page_ix].iov_base = (void *) 0;
} else {
page_count++;
if(!PageLocked(pp)) {
- LockPage(pp);
+ lock_page(pp);
}
/* save the page for background map */
code = afs_linux_fillpage(fp, pp);
if (!code)
code = afs_linux_prefetch(fp, pp);
- UnlockPage(pp);
+ unlock_page(pp);
}
return code;
return 0;
}
+/* Prepare an AFS vcache for writeback. Should be called with the vcache
+ * locked */
+static inline int
+afs_linux_prepare_writeback(struct vcache *avc) {
+ if (avc->f.states & CPageWrite) {
+ return AOP_WRITEPAGE_ACTIVATE;
+ }
+ avc->f.states |= CPageWrite;
+ return 0;
+}
+
+static inline int
+afs_linux_dopartialwrite(struct vcache *avc, cred_t *credp) {
+ struct vrequest treq;
+ int code = 0;
+
+ if (!afs_InitReq(&treq, credp))
+ code = afs_DoPartialWrite(avc, &treq);
+
+ return afs_convert_code(code);
+}
+
+static inline void
+afs_linux_complete_writeback(struct vcache *avc) {
+ avc->f.states &= ~CPageWrite;
+}
+
+/* Writeback a given page syncronously. Called with no AFS locks held */
static int
-afs_linux_writepage_sync(struct inode *ip, struct page *pp,
- unsigned long offset, unsigned int count)
+afs_linux_page_writeback(struct inode *ip, struct page *pp,
+ unsigned long offset, unsigned int count,
+ cred_t *credp)
{
struct vcache *vcp = VTOAFS(ip);
char *buffer;
afs_offs_t base;
int code = 0;
- cred_t *credp;
uio_t tuio;
struct iovec iovec;
int f_flags = 0;
buffer = kmap(pp) + offset;
base = page_offset(pp) + offset;
- credp = crref();
afs_maybe_lock_kernel();
AFS_GLOCK();
afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
ICL_TYPE_INT32, 99999);
- ObtainWriteLock(&vcp->lock, 532);
- if (vcp->f.states & CPageWrite) {
- ReleaseWriteLock(&vcp->lock);
- AFS_GUNLOCK();
- afs_maybe_unlock_kernel();
- crfree(credp);
- kunmap(pp);
- return AOP_WRITEPAGE_ACTIVATE;
- }
- vcp->f.states |= CPageWrite;
- ReleaseWriteLock(&vcp->lock);
-
setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
code = afs_write(vcp, &tuio, f_flags, credp, 0);
i_size_write(ip, vcp->f.m.Length);
ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
- ObtainWriteLock(&vcp->lock, 533);
- if (!code) {
- struct vrequest treq;
-
- if (!afs_InitReq(&treq, credp))
- code = afs_DoPartialWrite(vcp, &treq);
- }
code = code ? afs_convert_code(code) : count - tuio.uio_resid;
- vcp->f.states &= ~CPageWrite;
- ReleaseWriteLock(&vcp->lock);
-
afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
ICL_TYPE_INT32, code);
AFS_GUNLOCK();
afs_maybe_unlock_kernel();
- crfree(credp);
kunmap(pp);
return code;
}
+static int
+afs_linux_writepage_sync(struct inode *ip, struct page *pp,
+ unsigned long offset, unsigned int count)
+{
+ int code;
+ int code1 = 0;
+ struct vcache *vcp = VTOAFS(ip);
+ cred_t *credp;
+
+ /* Catch recursive writeback. This occurs if the kernel decides
+ * writeback is required whilst we are writing to the cache, or
+ * flushing to the server. */
+ AFS_GLOCK();
+ ObtainWriteLock(&vcp->lock, 532);
+ code = afs_linux_prepare_writeback(vcp);
+ if (code) {
+ ReleaseWriteLock(&vcp->lock);
+ AFS_GUNLOCK();
+ return code;
+ }
+ ReleaseWriteLock(&vcp->lock);
+ AFS_GUNLOCK();
+
+ credp = crref();
+ code = afs_linux_page_writeback(ip, pp, offset, count, credp);
+
+ afs_maybe_lock_kernel();
+ AFS_GLOCK();
+ ObtainWriteLock(&vcp->lock, 533);
+ if (code > 0)
+ code1 = afs_linux_dopartialwrite(vcp, credp);
+ afs_linux_complete_writeback(vcp);
+ ReleaseWriteLock(&vcp->lock);
+ AFS_GUNLOCK();
+ afs_maybe_unlock_kernel();
+ crfree(credp);
+
+ if (code1)
+ return code1;
+
+ return code;
+}
static int
#ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
SetPageUptodate(pp);
if ( status != AOP_WRITEPAGE_ACTIVATE ) {
/* XXX - do we need to redirty the page here? */
- UnlockPage(pp);
+ unlock_page(pp);
}
page_cache_release(pp);
SetPageUptodate(page);
kunmap(page);
- UnlockPage(page);
+ unlock_page(page);
return 0;
fail:
SetPageError(page);
kunmap(page);
- UnlockPage(page);
+ unlock_page(page);
return code;
}