Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147515722
D54338.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D54338.diff
View Options
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1620,6 +1620,7 @@
vm_inherit_t inheritance;
u_long bdry;
u_int bidx;
+ int cflags;
VM_MAP_ASSERT_LOCKED(map);
KASSERT(object != kernel_object ||
@@ -1696,20 +1697,36 @@
}
cred = NULL;
- if ((cow & (MAP_ACC_NO_CHARGE | MAP_NOFAULT | MAP_CREATE_GUARD)) != 0)
- goto charged;
- if ((cow & MAP_ACC_CHARGED) || ((prot & VM_PROT_WRITE) &&
- ((protoeflags & MAP_ENTRY_NEEDS_COPY) || object == NULL))) {
- if (!(cow & MAP_ACC_CHARGED) && !swap_reserve(end - start))
- return (KERN_RESOURCE_SHORTAGE);
- KASSERT(object == NULL ||
- (protoeflags & MAP_ENTRY_NEEDS_COPY) != 0 ||
- object->cred == NULL,
- ("overcommit: vm_map_insert o %p", object));
- cred = curthread->td_ucred;
+ if ((cow & (MAP_ACC_NO_CHARGE | MAP_NOFAULT | MAP_CREATE_GUARD)) != 0) {
+ cflags = OBJCO_NO_CHARGE;
+ } else {
+ cflags = 0;
+ if ((cow & MAP_ACC_CHARGED) != 0 ||
+ ((prot & VM_PROT_WRITE) != 0 &&
+ ((protoeflags & MAP_ENTRY_NEEDS_COPY) != 0 ||
+ object == NULL))) {
+ if ((cow & MAP_ACC_CHARGED) == 0) {
+ if (!swap_reserve(end - start))
+ return (KERN_RESOURCE_SHORTAGE);
+
+ /*
+ * Only inform vm_object_coalesce()
+ * that the object was charged if
+ * there is no need for CoW, so the
+ * swap amount reserved is applicable
+ * to the prev_entry->object.
+ */
+ if ((protoeflags & MAP_ENTRY_NEEDS_COPY) == 0)
+ cflags |= OBJCO_CHARGED;
+ }
+ KASSERT(object == NULL ||
+ (protoeflags & MAP_ENTRY_NEEDS_COPY) != 0 ||
+ object->cred == NULL,
+ ("overcommit: vm_map_insert o %p", object));
+ cred = curthread->td_ucred;
+ }
}
-charged:
/* Expand the kernel pmap, if necessary. */
if (map == kernel_map && end > kernel_vm_end) {
int rv;
@@ -1741,8 +1758,7 @@
vm_object_coalesce(prev_entry->object.vm_object,
prev_entry->offset,
(vm_size_t)(prev_entry->end - prev_entry->start),
- (vm_size_t)(end - prev_entry->end), cred != NULL &&
- (protoeflags & MAP_ENTRY_NEEDS_COPY) == 0)) {
+ (vm_size_t)(end - prev_entry->end), cflags)) {
/*
* We were able to extend the object. Determine if we
* can extend the previous map entry to include the
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -228,6 +228,12 @@
#define OBJPR_NOTMAPPED 0x2 /* Don't unmap pages. */
#define OBJPR_VALIDONLY 0x4 /* Ignore invalid pages. */
+/*
+ * Options for vm_object_coalesce().
+ */
+#define OBJCO_CHARGED 0x1 /* The next_size was charged already */
+#define OBJCO_NO_CHARGE 0x2 /* Do not do swap accounting at all */
+
TAILQ_HEAD(object_q, vm_object);
extern struct object_q vm_object_list; /* list of allocated objects */
@@ -354,7 +360,7 @@
vm_size_t);
vm_object_t vm_object_allocate_dyn(objtype_t, vm_pindex_t, u_short);
boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t,
- boolean_t);
+ int);
void vm_object_collapse (vm_object_t);
void vm_object_deallocate (vm_object_t);
void vm_object_destroy (vm_object_t);
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -2161,7 +2161,7 @@
*/
boolean_t
vm_object_coalesce(vm_object_t prev_object, vm_ooffset_t prev_offset,
- vm_size_t prev_size, vm_size_t next_size, boolean_t reserved)
+ vm_size_t prev_size, vm_size_t next_size, int cflags)
{
vm_pindex_t next_end, next_pindex;
@@ -2202,8 +2202,7 @@
/*
* Account for the charge.
*/
- if (prev_object->cred != NULL &&
- next_pindex + next_size > prev_object->size) {
+ if (prev_object->cred != NULL && (cflags & OBJCO_NO_CHARGE) == 0) {
/*
* If prev_object was charged, then this mapping,
* although not charged now, may become writable
@@ -2214,14 +2213,36 @@
* entry, and swap reservation for this entry is
* managed in appropriate time.
*/
- vm_size_t charge = ptoa(next_pindex + next_size -
- prev_object->size);
- if (!reserved &&
- !swap_reserve_by_cred(charge, prev_object->cred)) {
- VM_OBJECT_WUNLOCK(prev_object);
- return (FALSE);
+ if (next_end > prev_object->size) {
+ vm_size_t charge = ptoa(next_end - prev_object->size);
+
+ if ((cflags & OBJCO_CHARGED) == 0) {
+ if (!swap_reserve_by_cred(charge,
+ prev_object->cred)) {
+ VM_OBJECT_WUNLOCK(prev_object);
+ return (FALSE);
+ }
+ } else if (prev_object->size > next_pindex) {
+ /*
+ * The caller charged, but:
+ * - the object has already accounted for the
+ * space,
+ * - and the object end is between previous
+ * mapping end and next_end.
+ */
+ swap_release_by_cred(ptoa(prev_object->size -
+ next_pindex), prev_object->cred);
+ }
+ prev_object->charge += charge;
+ } else if ((cflags & OBJCO_CHARGED) != 0) {
+ /*
+ * The caller charged, but the object has
+ * already accounted for the space. Whole new
+ * mapping charge should be released,
+ */
+ swap_release_by_cred(ptoa(next_size),
+ prev_object->cred);
}
- prev_object->charge += charge;
}
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 12, 1:59 PM (6 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29585349
Default Alt Text
D54338.diff (5 KB)
Attached To
Mode
D54338: vm_object_coalesce(): return swap reservation back if overcharged
Attached
Detach File
Event Timeline
Log In to Comment