#endif
static int naccess(struct nchandle *nch, int vmode, struct ucred *cred,
- int *stickyp, int *cflagsp);
+ int *stickyp);
/*
* Initialize a nlookup() structure, early error return for copyin faults
int error;
int len;
int dflags;
- int cflags;
#ifdef KTRACE
if (KTRPOINT(nd->nl_td, KTR_NAMEI))
* Loop on the path components. At the top of the loop nd->nl_nch
* is ref'd and unlocked and represents our current position.
*/
- cflags = nd->nl_nch.ncp->nc_flag & (NCF_SF_PNOCACHE | NCF_UF_PCACHE);
for (;;) {
/*
* Make sure nl_nch is locked so we can access the vnode, resolution
* Check directory search permissions.
*/
dflags = 0;
- error = naccess(&nd->nl_nch, NLC_EXEC, nd->nl_cred, &dflags, &cflags);
+ error = naccess(&nd->nl_nch, NLC_EXEC, nd->nl_cred, &dflags);
if (error)
break;
par.mount = nch.mount;
cache_hold(&par);
cache_lock(&par);
- cflags = par.ncp->nc_flag & (NCF_SF_PNOCACHE | NCF_UF_PCACHE);
- error = naccess(&par, 0, nd->nl_cred, &dflags, &cflags);
+ error = naccess(&par, 0, nd->nl_cred, &dflags);
cache_put(&par);
}
}
error = EROFS;
} else {
error = naccess(&nch, nd->nl_flags | dflags,
- nd->nl_cred, NULL, &cflags);
+ nd->nl_cred, NULL);
}
}
if (error == 0 && wasdotordotdot &&
*/
if (nch.ncp->nc_vp && (nd->nl_flags & NLC_ALLCHKS)) {
error = naccess(&nch, nd->nl_flags | dflags,
- nd->nl_cred, NULL, &cflags);
+ nd->nl_cred, NULL);
if (error) {
cache_put(&nch);
break;
* The passed ncp must be referenced and locked.
*/
int
-naccess(struct nchandle *nch, int nflags, struct ucred *cred,
- int *nflagsp, int *cflagsp)
+naccess(struct nchandle *nch, int nflags, struct ucred *cred, int *nflagsp)
{
struct vnode *vp;
struct vattr va;
+ struct namecache *ncp;
int error;
int cflags;
ASSERT_NCH_LOCKED(nch);
- if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
+ ncp = nch->ncp;
+ if (ncp->nc_flag & NCF_UNRESOLVED) {
cache_resolve(nch, cred);
+ ncp = nch->ncp;
}
- error = nch->ncp->nc_error;
+ error = ncp->nc_error;
/*
* Directory permissions checks. Silently ignore ENOENT if these
* tests pass. It isn't an error.
*
- * We have to lock nch.ncp to safely resolve nch.ncp->nc_parent
+ * We can safely resolve ncp->nc_parent because ncp is currently
+ * locked.
*/
if (nflags & (NLC_CREATE | NLC_DELETE | NLC_RENAME_SRC | NLC_RENAME_DST)) {
- if (((nflags & NLC_CREATE) && nch->ncp->nc_vp == NULL) ||
- ((nflags & NLC_DELETE) && nch->ncp->nc_vp != NULL) ||
- ((nflags & NLC_RENAME_SRC) && nch->ncp->nc_vp != NULL) ||
+ if (((nflags & NLC_CREATE) && ncp->nc_vp == NULL) ||
+ ((nflags & NLC_DELETE) && ncp->nc_vp != NULL) ||
+ ((nflags & NLC_RENAME_SRC) && ncp->nc_vp != NULL) ||
(nflags & NLC_RENAME_DST)
) {
struct nchandle par;
- if ((par.ncp = nch->ncp->nc_parent) == NULL) {
+ if ((par.ncp = ncp->nc_parent) == NULL) {
if (error != EAGAIN)
error = EINVAL;
} else if (error == 0 || error == ENOENT) {
par.mount = nch->mount;
cache_hold(&par);
cache_lock(&par);
- cflags = par.ncp->nc_flag & (NCF_SF_PNOCACHE | NCF_UF_PCACHE);
- error = naccess(&par, NLC_WRITE, cred, NULL, &cflags);
+ error = naccess(&par, NLC_WRITE, cred, NULL);
cache_put(&par);
}
}
/*
* NLC_EXCL check. Target file must not exist.
*/
- if (error == 0 && (nflags & NLC_EXCL) && nch->ncp->nc_vp != NULL)
+ if (error == 0 && (nflags & NLC_EXCL) && ncp->nc_vp != NULL)
error = EEXIST;
/*
/*
* Track swapcache management flags in the namecache.
- * (*cflagsp) tracks and returns the cumulative parent state
- * while nc_flag gets the old parent state and the new
- * flags state from the vap.
+ *
+ * Calculate the flags based on the current vattr info
+ * and recalculate the inherited flags from the parent
+ * (the original cache linkage may have occurred without
+ * getattrs and thus have stale flags).
*/
- cflags = *cflagsp;
- nch->ncp->nc_flag &= ~(NCF_SF_PNOCACHE | NCF_UF_PCACHE);
- nch->ncp->nc_flag |= cflags;
-
+ cflags = 0;
if (va.va_flags & SF_NOCACHE)
- cflags |= NCF_SF_PNOCACHE | NCF_SF_NOCACHE;
+ cflags |= NCF_SF_NOCACHE;
if (va.va_flags & UF_CACHE)
- cflags |= NCF_UF_PCACHE | NCF_UF_CACHE;
- *cflagsp = cflags & (NCF_SF_PNOCACHE | NCF_UF_PCACHE);
- nch->ncp->nc_flag &= ~(NCF_SF_NOCACHE | NCF_UF_CACHE);
- nch->ncp->nc_flag |= cflags & (NCF_SF_NOCACHE | NCF_UF_CACHE);
+ cflags |= NCF_UF_CACHE;
+ if (ncp->nc_parent) {
+ if (ncp->nc_parent->nc_flag &
+ (NCF_SF_NOCACHE | NCF_SF_PNOCACHE)) {
+ cflags |= NCF_SF_PNOCACHE;
+ }
+ if (ncp->nc_parent->nc_flag &
+ (NCF_UF_CACHE | NCF_UF_PCACHE)) {
+ cflags |= NCF_UF_PCACHE;
+ }
+ }
+ ncp->nc_flag &= ~(NCF_SF_NOCACHE | NCF_UF_CACHE |
+ NCF_SF_PNOCACHE | NCF_UF_PCACHE);
+ ncp->nc_flag |= cflags;
/*
* Process general access.
/* the kernel process "vm_pageout"*/
static void vm_swapcached (void);
-static int vm_swapcached_flush (vm_page_t m);
+static int vm_swapcached_flush (vm_page_t m, int isblkdev);
static int vm_swapcache_test(vm_page_t m);
static void vm_swapcache_writing(vm_page_t marker);
static void vm_swapcache_cleaning(vm_object_t marker);
struct vnode *vp;
vm_page_t m;
int count;
+ int isblkdev;
/*
* Deal with an overflow of the heuristic counter or if the user
(vm_swapcache_maxfilesize >> PAGE_SHIFT)) {
continue;
}
+ isblkdev = 0;
break;
case VCHR:
+ /*
+ * The PG_NOTMETA flag only applies to pages
+ * associated with block devices.
+ */
+ if (m->flags & PG_NOTMETA)
+ continue;
if (vm_swapcache_meta_enable == 0)
continue;
+ isblkdev = 1;
break;
default:
continue;
*
* (adjust for the --count which also occurs in the loop)
*/
- count -= vm_swapcached_flush(m) - 1;
+ count -= vm_swapcached_flush(m, isblkdev) - 1;
/*
* Setup for next loop using marker.
*/
static
int
-vm_swapcached_flush(vm_page_t m)
+vm_swapcached_flush(vm_page_t m, int isblkdev)
{
vm_object_t object;
vm_page_t marray[SWAP_META_PAGES];
break;
if (vm_swapcache_test(m))
break;
+ if (isblkdev && (m->flags & PG_NOTMETA))
+ break;
vm_page_io_start(m);
vm_page_protect(m, VM_PROT_READ);
if (m->queue - m->pc == PQ_CACHE) {
break;
if (vm_swapcache_test(m))
break;
+ if (isblkdev && (m->flags & PG_NOTMETA))
+ break;
vm_page_io_start(m);
vm_page_protect(m, VM_PROT_READ);
if (m->queue - m->pc == PQ_CACHE) {
{
vm_object_t object;
- if (m->flags & (PG_BUSY | PG_UNMANAGED | PG_NOTMETA))
+ if (m->flags & (PG_BUSY | PG_UNMANAGED))
return(1);
if (m->busy || m->hold_count || m->wire_count)
return(1);