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 ---