diff options
author | Michael I. Bushnell <mib@gnu.org> | 1995-07-21 21:58:08 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1995-07-21 21:58:08 +0000 |
commit | 9003138387cca2e16d004b952c5d0f65a9364cc0 (patch) | |
tree | 0dbb6bdb3866e40f31ee59efaf4cbbdd39be10bf /ufs | |
parent | 13e34674ce5c20de9a499c7a25f26a57a0ed9a44 (diff) |
(diskfs_get_filemap): Drop initial reference created by pager_create.
(pager_clear_user_data): Only clear UPI->np->dn->fileinfo if it still
points to us.
Diffstat (limited to 'ufs')
-rw-r--r-- | ufs/pager.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/ufs/pager.c b/ufs/pager.c index 139e5723..cac6836a 100644 --- a/ufs/pager.c +++ b/ufs/pager.c @@ -362,7 +362,8 @@ pager_clear_user_data (struct user_pager_info *upi) if (upi->type == FILE_DATA) { spin_lock (&node2pagelock); - upi->np->dn->fileinfo = 0; + if (upi->np->dn->fileinfo == upi) + upi->np->dn->fileinfo = 0; spin_unlock (&node2pagelock); diskfs_nrele_light (upi->np); } @@ -450,24 +451,30 @@ diskfs_get_filemap (struct node *np) || np->dn_stat.st_size >= sblock->fs_maxsymlinklen))); spin_lock (&node2pagelock); - if (!np->dn->fileinfo) - { - upi = malloc (sizeof (struct user_pager_info)); - upi->type = FILE_DATA; - upi->np = np; - diskfs_nref_light (np); - upi->p = pager_create (upi, pager_bucket, - MAY_CACHE, MEMORY_OBJECT_COPY_DELAY); - np->dn->fileinfo = upi; - right = pager_get_port (np->dn->fileinfo->p); - ports_port_deref (np->dn->fileinfo->p); - } - else - /* There is a race condition here. If there are no references - to NP->dn->fileinfo->p, then the clean routine might be - blocked trying to get into node2pagelock, and this call is - invalid. XXX */ - right = pager_get_port (np->dn->fileinfo->p); + do + if (!np->dn->fileinfo) + { + upi = malloc (sizeof (struct user_pager_info)); + upi->type = FILE_DATA; + upi->np = np; + diskfs_nref_light (np); + upi->p = pager_create (upi, pager_bucket, + MAY_CACHE, MEMORY_OBJECT_COPY_DELAY); + np->dn->fileinfo = upi; + right = pager_get_port (np->dn->fileinfo->p); + ports_port_deref (np->dn->fileinfo->p); + } + else + { + /* Because NP->dn->fileinfo->p is not a real reference, + this might be nearly deallocated. If that's so, then + the port right will be null. In that case, clear here + and loop. The deallocation will complete separately. */ + right = pager_get_port (np->dn->fileinfo->p); + if (right == MACH_PORT_NULL) + np->dn->fileinfo = 0; + } + while (right == MACH_PORT_NULL); spin_unlock (&node2pagelock); |