afs_maybe_lock_kernel();
AFS_GLOCK();
code = afs_close(vcp, fp->f_flags, credp);
+ ObtainWriteLock(&vcp->lock, 807);
+ if (vcp->cred) {
+ crfree(vcp->cred);
+ vcp->cred = NULL;
+ }
+ ReleaseWriteLock(&vcp->lock);
AFS_GUNLOCK();
afs_maybe_unlock_kernel();
dput(alias);
} else {
iput(ip);
- unlock_kernel();
+ afs_maybe_unlock_kernel();
crfree(credp);
return alias;
}
afs_offs_t offset;
struct iovec* iovecp;
struct nocache_read_request *ancr;
- struct page *pp, *ppt;
+ struct page *pp;
struct pagevec lrupv;
afs_int32 code = 0;
/* we do not flush, release, or unmap pages--that will be
* done for us by the background thread as each page comes in
* from the fileserver */
-out:
return afs_convert_code(code);
}
uio_t *auio;
struct iovec *iovecp;
struct nocache_read_request *ancr;
- afs_int32 isize;
+ int code;
ClearPageError(pp);
/* the background thread will free this */
ancr = osi_Alloc(sizeof(struct nocache_read_request));
ancr->auio = auio;
- ancr->offset = offset;
+ ancr->offset = page_offset(pp);
ancr->length = PAGE_SIZE;
credp = crref();
if(i_size_read(ip) > cache_bypass_threshold)
return 1;
default:
+ return 0;
}
- return 0;
}
/* Check if a file is permitted to bypass the cache by policy, and modify
static inline int
afs_linux_bypass_check(struct inode *ip) {
- struct cred* credp;
+ cred_t* credp;
int bypass = afs_linux_can_bypass(ip);
credp = crref();
- trydo_cache_transition(VTOAFS(ip)), credp, bypass);
+ trydo_cache_transition(VTOAFS(ip), credp, bypass);
crfree(credp);
return bypass;
static inline int
afs_linux_dopartialwrite(struct vcache *avc, cred_t *credp) {
struct vrequest treq;
- int code;
+ int code = 0;
if (!afs_InitReq(&treq, credp))
code = afs_DoPartialWrite(avc, &treq);
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. */
+ * flushing to the server. When we're running syncronously (as
+ * opposed to from writepage) we can't actually do anything about
+ * this case - as we can't return AOP_WRITEPAGE_ACTIVATE to write()
+ */
AFS_GLOCK();
ObtainWriteLock(&vcp->lock, 532);
- code = afs_linux_prepare_writeback(vcp);
- if (code) {
- ReleaseWriteLock(&vcp->lock);
- AFS_GUNLOCK();
- return code;
- }
+ afs_linux_prepare_writeback(vcp);
ReleaseWriteLock(&vcp->lock);
AFS_GUNLOCK();
afs_maybe_lock_kernel();
AFS_GLOCK();
ObtainWriteLock(&vcp->lock, 533);
- if (code == 0)
- code = afs_linux_dopartialwrite(vcp, credp);
+ 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;
}
{
struct address_space *mapping = pp->mapping;
struct inode *inode;
+ struct vcache *vcp;
+ cred_t *credp;
unsigned int to = PAGE_CACHE_SIZE;
loff_t isize;
- int status = 0;
+ int code = 0;
+ int code1 = 0;
if (PageReclaim(pp)) {
return AOP_WRITEPAGE_ACTIVATE;
page_cache_get(pp);
- inode = (struct inode *)mapping->host;
+ inode = mapping->host;
+ vcp = VTOAFS(inode);
isize = i_size_read(inode);
/* Don't defeat an earlier truncate */
if (page_offset(pp) > isize)
goto done;
+ AFS_GLOCK();
+ ObtainWriteLock(&vcp->lock, 537);
+ code = afs_linux_prepare_writeback(vcp);
+ if (code) {
+ ReleaseWriteLock(&vcp->lock);
+ AFS_GUNLOCK();
+ return code;
+ }
+ /* Grab the creds structure currently held in the vnode, and
+ * get a reference to it, in case it goes away ... */
+ credp = vcp->cred;
+ crhold(credp);
+ ReleaseWriteLock(&vcp->lock);
+ AFS_GUNLOCK();
+
/* If this is the final page, then just write the number of bytes that
* are actually in it */
if ((isize - page_offset(pp)) < to )
to = isize - page_offset(pp);
- status = afs_linux_writepage_sync(inode, pp, 0, to);
+ code = afs_linux_page_writeback(inode, pp, 0, to, credp);
+
+ afs_maybe_lock_kernel();
+ AFS_GLOCK();
+ ObtainWriteLock(&vcp->lock, 538);
+
+ /* As much as we might like to ignore a file server error here,
+ * and just try again when we close(), unfortunately StoreAllSegments
+ * will invalidate our chunks if the server returns a permanent error,
+ * so we need to at least try and get that error back to the user
+ */
+ if (code == to)
+ code1 = afs_linux_dopartialwrite(vcp, credp);
+
+ afs_linux_complete_writeback(vcp);
+ ReleaseWriteLock(&vcp->lock);
+ crfree(credp);
+ AFS_GUNLOCK();
+ afs_maybe_unlock_kernel();
done:
SetPageUptodate(pp);
- if ( status != AOP_WRITEPAGE_ACTIVATE ) {
+ if ( code != AOP_WRITEPAGE_ACTIVATE ) {
/* XXX - do we need to redirty the page here? */
unlock_page(pp);
}
page_cache_release(pp);
- if (status == to)
+ if (code1)
+ return code1;
+
+ if (code == to)
return 0;
- else
- return status;
+
+ return code;
}
/* afs_linux_permission