/* Allocate a slot for hibernation */
swp_entry_t swap_alloc_hibernation_slot(int type)
{
- struct swap_info_struct *si = swap_type_to_info(type);
- unsigned long offset;
+ struct swap_info_struct *pcp_si, *si = swap_type_to_info(type);
+ unsigned long pcp_offset, offset = SWAP_ENTRY_INVALID;
+ struct swap_cluster_info *ci;
swp_entry_t entry = {0};
if (!si)
if (get_swap_device_info(si)) {
if (si->flags & SWP_WRITEOK) {
/*
- * Grab the local lock to be compliant
- * with swap table allocation.
+ * Try the local cluster first if it matches the device. If
+ * not, try grab a new cluster and override local cluster.
*/
local_lock(&percpu_swap_cluster.lock);
- offset = cluster_alloc_swap_entry(si, NULL);
+ pcp_si = this_cpu_read(percpu_swap_cluster.si[0]);
+ pcp_offset = this_cpu_read(percpu_swap_cluster.offset[0]);
+ if (pcp_si == si && pcp_offset) {
+ ci = swap_cluster_lock(si, pcp_offset);
+ if (cluster_is_usable(ci, 0))
+ offset = alloc_swap_scan_cluster(si, ci, NULL, pcp_offset);
+ else
+ swap_cluster_unlock(ci);
+ }
+ if (!offset)
+ offset = cluster_alloc_swap_entry(si, NULL);
local_unlock(&percpu_swap_cluster.lock);
if (offset)
entry = swp_entry(si->type, offset);