shmem.c (f21f8062201fc6361f65de92e758a76375ba8c59) | shmem.c (d189922862e03ce6c7adc1e99d3b94e632dc8e89) |
---|---|
1/* 2 * Resizable virtual memory filesystem for Linux. 3 * 4 * Copyright (C) 2000 Linus Torvalds. 5 * 2000 Transmeta Corp. 6 * 2000-2001 Christoph Rohland 7 * 2000-2001 SAP AG 8 * 2002 Red Hat Inc. --- 250 unchanged lines hidden (view full) --- 259 if (replacement) 260 radix_tree_replace_slot(pslot, replacement); 261 else 262 radix_tree_delete(&mapping->page_tree, index); 263 return 0; 264} 265 266/* | 1/* 2 * Resizable virtual memory filesystem for Linux. 3 * 4 * Copyright (C) 2000 Linus Torvalds. 5 * 2000 Transmeta Corp. 6 * 2000-2001 Christoph Rohland 7 * 2000-2001 SAP AG 8 * 2002 Red Hat Inc. --- 250 unchanged lines hidden (view full) --- 259 if (replacement) 260 radix_tree_replace_slot(pslot, replacement); 261 else 262 radix_tree_delete(&mapping->page_tree, index); 263 return 0; 264} 265 266/* |
267 * Sometimes, before we decide whether to proceed or to fail, we must check 268 * that an entry was not already brought back from swap by a racing thread. 269 * 270 * Checking page is not enough: by the time a SwapCache page is locked, it 271 * might be reused, and again be SwapCache, using the same swap as before. 272 */ 273static bool shmem_confirm_swap(struct address_space *mapping, 274 pgoff_t index, swp_entry_t swap) 275{ 276 void *item; 277 278 rcu_read_lock(); 279 item = radix_tree_lookup(&mapping->page_tree, index); 280 rcu_read_unlock(); 281 return item == swp_to_radix_entry(swap); 282} 283 284/* |
|
267 * Like add_to_page_cache_locked, but error if expected item has gone. 268 */ 269static int shmem_add_to_page_cache(struct page *page, 270 struct address_space *mapping, 271 pgoff_t index, gfp_t gfp, void *expected) 272{ 273 int error = 0; 274 --- 844 unchanged lines hidden (view full) --- 1119 error = -ENOMEM; 1120 goto failed; 1121 } 1122 } 1123 1124 /* We have to do this with page locked to prevent races */ 1125 lock_page(page); 1126 if (!PageSwapCache(page) || page_private(page) != swap.val || | 285 * Like add_to_page_cache_locked, but error if expected item has gone. 286 */ 287static int shmem_add_to_page_cache(struct page *page, 288 struct address_space *mapping, 289 pgoff_t index, gfp_t gfp, void *expected) 290{ 291 int error = 0; 292 --- 844 unchanged lines hidden (view full) --- 1137 error = -ENOMEM; 1138 goto failed; 1139 } 1140 } 1141 1142 /* We have to do this with page locked to prevent races */ 1143 lock_page(page); 1144 if (!PageSwapCache(page) || page_private(page) != swap.val || |
1127 page->mapping) { | 1145 !shmem_confirm_swap(mapping, index, swap)) { |
1128 error = -EEXIST; /* try again */ | 1146 error = -EEXIST; /* try again */ |
1129 goto failed; | 1147 goto unlock; |
1130 } 1131 if (!PageUptodate(page)) { 1132 error = -EIO; 1133 goto failed; 1134 } 1135 wait_on_page_writeback(page); 1136 1137 if (shmem_should_replace_page(page, gfp)) { 1138 error = shmem_replace_page(&page, gfp, info, index); 1139 if (error) 1140 goto failed; 1141 } 1142 1143 error = mem_cgroup_cache_charge(page, current->mm, 1144 gfp & GFP_RECLAIM_MASK); | 1148 } 1149 if (!PageUptodate(page)) { 1150 error = -EIO; 1151 goto failed; 1152 } 1153 wait_on_page_writeback(page); 1154 1155 if (shmem_should_replace_page(page, gfp)) { 1156 error = shmem_replace_page(&page, gfp, info, index); 1157 if (error) 1158 goto failed; 1159 } 1160 1161 error = mem_cgroup_cache_charge(page, current->mm, 1162 gfp & GFP_RECLAIM_MASK); |
1145 if (!error) | 1163 if (!error) { |
1146 error = shmem_add_to_page_cache(page, mapping, index, 1147 gfp, swp_to_radix_entry(swap)); | 1164 error = shmem_add_to_page_cache(page, mapping, index, 1165 gfp, swp_to_radix_entry(swap)); |
1166 /* We already confirmed swap, and make no allocation */ 1167 VM_BUG_ON(error); 1168 } |
|
1148 if (error) 1149 goto failed; 1150 1151 spin_lock(&info->lock); 1152 info->swapped--; 1153 shmem_recalc_inode(inode); 1154 spin_unlock(&info->lock); 1155 --- 84 unchanged lines hidden (view full) --- 1240 spin_unlock(&info->lock); 1241decused: 1242 sbinfo = SHMEM_SB(inode->i_sb); 1243 if (sbinfo->max_blocks) 1244 percpu_counter_add(&sbinfo->used_blocks, -1); 1245unacct: 1246 shmem_unacct_blocks(info->flags, 1); 1247failed: | 1169 if (error) 1170 goto failed; 1171 1172 spin_lock(&info->lock); 1173 info->swapped--; 1174 shmem_recalc_inode(inode); 1175 spin_unlock(&info->lock); 1176 --- 84 unchanged lines hidden (view full) --- 1261 spin_unlock(&info->lock); 1262decused: 1263 sbinfo = SHMEM_SB(inode->i_sb); 1264 if (sbinfo->max_blocks) 1265 percpu_counter_add(&sbinfo->used_blocks, -1); 1266unacct: 1267 shmem_unacct_blocks(info->flags, 1); 1268failed: |
1248 if (swap.val && error != -EINVAL) { 1249 struct page *test = find_get_page(mapping, index); 1250 if (test && !radix_tree_exceptional_entry(test)) 1251 page_cache_release(test); 1252 /* Have another try if the entry has changed */ 1253 if (test != swp_to_radix_entry(swap)) 1254 error = -EEXIST; 1255 } | 1269 if (swap.val && error != -EINVAL && 1270 !shmem_confirm_swap(mapping, index, swap)) 1271 error = -EEXIST; 1272unlock: |
1256 if (page) { 1257 unlock_page(page); 1258 page_cache_release(page); 1259 } 1260 if (error == -ENOSPC && !once++) { 1261 info = SHMEM_I(inode); 1262 spin_lock(&info->lock); 1263 shmem_recalc_inode(inode); 1264 spin_unlock(&info->lock); 1265 goto repeat; 1266 } | 1273 if (page) { 1274 unlock_page(page); 1275 page_cache_release(page); 1276 } 1277 if (error == -ENOSPC && !once++) { 1278 info = SHMEM_I(inode); 1279 spin_lock(&info->lock); 1280 shmem_recalc_inode(inode); 1281 spin_unlock(&info->lock); 1282 goto repeat; 1283 } |
1267 if (error == -EEXIST) | 1284 if (error == -EEXIST) /* from above or from radix_tree_insert */ |
1268 goto repeat; 1269 return error; 1270} 1271 1272static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 1273{ 1274 struct inode *inode = vma->vm_file->f_path.dentry->d_inode; 1275 int error; --- 1733 unchanged lines hidden --- | 1285 goto repeat; 1286 return error; 1287} 1288 1289static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 1290{ 1291 struct inode *inode = vma->vm_file->f_path.dentry->d_inode; 1292 int error; --- 1733 unchanged lines hidden --- |