Skip to content

Commit d3c1b24

Browse files
Jiri Slabyrjwysocki
authored andcommitted
PM / Hibernate: Snapshot cleanup
Remove support of reads with offset. This means snapshot_read/write_next now does not accept count parameter. It allows to clean up the functions and snapshot handle which no longer needs to care about offsets. /dev/snapshot handler is converted to simple_{read_from,write_to}_buffer which take care of offsets. Signed-off-by: Jiri Slaby <[email protected]> Acked-by: Pavel Machek <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 6a727b4 commit d3c1b24

File tree

4 files changed

+88
-120
lines changed

4 files changed

+88
-120
lines changed

kernel/power/power.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,24 +97,12 @@ extern int hibernate_preallocate_memory(void);
9797
*/
9898

9999
struct snapshot_handle {
100-
loff_t offset; /* number of the last byte ready for reading
101-
* or writing in the sequence
102-
*/
103100
unsigned int cur; /* number of the block of PAGE_SIZE bytes the
104101
* next operation will refer to (ie. current)
105102
*/
106-
unsigned int cur_offset; /* offset with respect to the current
107-
* block (for the next operation)
108-
*/
109-
unsigned int prev; /* number of the block of PAGE_SIZE bytes that
110-
* was the current one previously
111-
*/
112103
void *buffer; /* address of the block to read from
113104
* or write to
114105
*/
115-
unsigned int buf_offset; /* location to read from or write to,
116-
* given as a displacement from 'buffer'
117-
*/
118106
int sync_read; /* Set to one to notify the caller of
119107
* snapshot_write_next() that it may
120108
* need to call wait_on_bio_chain()
@@ -125,12 +113,12 @@ struct snapshot_handle {
125113
* snapshot_read_next()/snapshot_write_next() is allowed to
126114
* read/write data after the function returns
127115
*/
128-
#define data_of(handle) ((handle).buffer + (handle).buf_offset)
116+
#define data_of(handle) ((handle).buffer)
129117

130118
extern unsigned int snapshot_additional_pages(struct zone *zone);
131119
extern unsigned long snapshot_get_image_size(void);
132-
extern int snapshot_read_next(struct snapshot_handle *handle, size_t count);
133-
extern int snapshot_write_next(struct snapshot_handle *handle, size_t count);
120+
extern int snapshot_read_next(struct snapshot_handle *handle);
121+
extern int snapshot_write_next(struct snapshot_handle *handle);
134122
extern void snapshot_write_finalize(struct snapshot_handle *handle);
135123
extern int snapshot_image_loaded(struct snapshot_handle *handle);
136124

kernel/power/snapshot.c

Lines changed: 56 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,22 +1604,17 @@ pack_pfns(unsigned long *buf, struct memory_bitmap *bm)
16041604
* snapshot_handle structure. The structure gets updated and a pointer
16051605
* to it should be passed to this function every next time.
16061606
*
1607-
* The @count parameter should contain the number of bytes the caller
1608-
* wants to read from the snapshot. It must not be zero.
1609-
*
16101607
* On success the function returns a positive number. Then, the caller
16111608
* is allowed to read up to the returned number of bytes from the memory
1612-
* location computed by the data_of() macro. The number returned
1613-
* may be smaller than @count, but this only happens if the read would
1614-
* cross a page boundary otherwise.
1609+
* location computed by the data_of() macro.
16151610
*
16161611
* The function returns 0 to indicate the end of data stream condition,
16171612
* and a negative number is returned on error. In such cases the
16181613
* structure pointed to by @handle is not updated and should not be used
16191614
* any more.
16201615
*/
16211616

1622-
int snapshot_read_next(struct snapshot_handle *handle, size_t count)
1617+
int snapshot_read_next(struct snapshot_handle *handle)
16231618
{
16241619
if (handle->cur > nr_meta_pages + nr_copy_pages)
16251620
return 0;
@@ -1630,7 +1625,7 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
16301625
if (!buffer)
16311626
return -ENOMEM;
16321627
}
1633-
if (!handle->offset) {
1628+
if (!handle->cur) {
16341629
int error;
16351630

16361631
error = init_header((struct swsusp_info *)buffer);
@@ -1639,42 +1634,30 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
16391634
handle->buffer = buffer;
16401635
memory_bm_position_reset(&orig_bm);
16411636
memory_bm_position_reset(&copy_bm);
1642-
}
1643-
if (handle->prev < handle->cur) {
1644-
if (handle->cur <= nr_meta_pages) {
1645-
memset(buffer, 0, PAGE_SIZE);
1646-
pack_pfns(buffer, &orig_bm);
1647-
} else {
1648-
struct page *page;
1637+
} else if (handle->cur <= nr_meta_pages) {
1638+
memset(buffer, 0, PAGE_SIZE);
1639+
pack_pfns(buffer, &orig_bm);
1640+
} else {
1641+
struct page *page;
16491642

1650-
page = pfn_to_page(memory_bm_next_pfn(&copy_bm));
1651-
if (PageHighMem(page)) {
1652-
/* Highmem pages are copied to the buffer,
1653-
* because we can't return with a kmapped
1654-
* highmem page (we may not be called again).
1655-
*/
1656-
void *kaddr;
1643+
page = pfn_to_page(memory_bm_next_pfn(&copy_bm));
1644+
if (PageHighMem(page)) {
1645+
/* Highmem pages are copied to the buffer,
1646+
* because we can't return with a kmapped
1647+
* highmem page (we may not be called again).
1648+
*/
1649+
void *kaddr;
16571650

1658-
kaddr = kmap_atomic(page, KM_USER0);
1659-
memcpy(buffer, kaddr, PAGE_SIZE);
1660-
kunmap_atomic(kaddr, KM_USER0);
1661-
handle->buffer = buffer;
1662-
} else {
1663-
handle->buffer = page_address(page);
1664-
}
1651+
kaddr = kmap_atomic(page, KM_USER0);
1652+
memcpy(buffer, kaddr, PAGE_SIZE);
1653+
kunmap_atomic(kaddr, KM_USER0);
1654+
handle->buffer = buffer;
1655+
} else {
1656+
handle->buffer = page_address(page);
16651657
}
1666-
handle->prev = handle->cur;
1667-
}
1668-
handle->buf_offset = handle->cur_offset;
1669-
if (handle->cur_offset + count >= PAGE_SIZE) {
1670-
count = PAGE_SIZE - handle->cur_offset;
1671-
handle->cur_offset = 0;
1672-
handle->cur++;
1673-
} else {
1674-
handle->cur_offset += count;
16751658
}
1676-
handle->offset += count;
1677-
return count;
1659+
handle->cur++;
1660+
return PAGE_SIZE;
16781661
}
16791662

16801663
/**
@@ -2133,31 +2116,28 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
21332116
* snapshot_handle structure. The structure gets updated and a pointer
21342117
* to it should be passed to this function every next time.
21352118
*
2136-
* The @count parameter should contain the number of bytes the caller
2137-
* wants to write to the image. It must not be zero.
2138-
*
21392119
* On success the function returns a positive number. Then, the caller
21402120
* is allowed to write up to the returned number of bytes to the memory
2141-
* location computed by the data_of() macro. The number returned
2142-
* may be smaller than @count, but this only happens if the write would
2143-
* cross a page boundary otherwise.
2121+
* location computed by the data_of() macro.
21442122
*
21452123
* The function returns 0 to indicate the "end of file" condition,
21462124
* and a negative number is returned on error. In such cases the
21472125
* structure pointed to by @handle is not updated and should not be used
21482126
* any more.
21492127
*/
21502128

2151-
int snapshot_write_next(struct snapshot_handle *handle, size_t count)
2129+
int snapshot_write_next(struct snapshot_handle *handle)
21522130
{
21532131
static struct chain_allocator ca;
21542132
int error = 0;
21552133

21562134
/* Check if we have already loaded the entire image */
2157-
if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages)
2135+
if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages)
21582136
return 0;
21592137

2160-
if (handle->offset == 0) {
2138+
handle->sync_read = 1;
2139+
2140+
if (!handle->cur) {
21612141
if (!buffer)
21622142
/* This makes the buffer be freed by swsusp_free() */
21632143
buffer = get_image_page(GFP_ATOMIC, PG_ANY);
@@ -2166,56 +2146,43 @@ int snapshot_write_next(struct snapshot_handle *handle, size_t count)
21662146
return -ENOMEM;
21672147

21682148
handle->buffer = buffer;
2169-
}
2170-
handle->sync_read = 1;
2171-
if (handle->prev < handle->cur) {
2172-
if (handle->prev == 0) {
2173-
error = load_header(buffer);
2174-
if (error)
2175-
return error;
2149+
} else if (handle->cur == 1) {
2150+
error = load_header(buffer);
2151+
if (error)
2152+
return error;
21762153

2177-
error = memory_bm_create(&copy_bm, GFP_ATOMIC, PG_ANY);
2178-
if (error)
2179-
return error;
2154+
error = memory_bm_create(&copy_bm, GFP_ATOMIC, PG_ANY);
2155+
if (error)
2156+
return error;
2157+
2158+
} else if (handle->cur <= nr_meta_pages + 1) {
2159+
error = unpack_orig_pfns(buffer, &copy_bm);
2160+
if (error)
2161+
return error;
21802162

2181-
} else if (handle->prev <= nr_meta_pages) {
2182-
error = unpack_orig_pfns(buffer, &copy_bm);
2163+
if (handle->cur == nr_meta_pages + 1) {
2164+
error = prepare_image(&orig_bm, &copy_bm);
21832165
if (error)
21842166
return error;
21852167

2186-
if (handle->prev == nr_meta_pages) {
2187-
error = prepare_image(&orig_bm, &copy_bm);
2188-
if (error)
2189-
return error;
2190-
2191-
chain_init(&ca, GFP_ATOMIC, PG_SAFE);
2192-
memory_bm_position_reset(&orig_bm);
2193-
restore_pblist = NULL;
2194-
handle->buffer = get_buffer(&orig_bm, &ca);
2195-
handle->sync_read = 0;
2196-
if (IS_ERR(handle->buffer))
2197-
return PTR_ERR(handle->buffer);
2198-
}
2199-
} else {
2200-
copy_last_highmem_page();
2168+
chain_init(&ca, GFP_ATOMIC, PG_SAFE);
2169+
memory_bm_position_reset(&orig_bm);
2170+
restore_pblist = NULL;
22012171
handle->buffer = get_buffer(&orig_bm, &ca);
2172+
handle->sync_read = 0;
22022173
if (IS_ERR(handle->buffer))
22032174
return PTR_ERR(handle->buffer);
2204-
if (handle->buffer != buffer)
2205-
handle->sync_read = 0;
22062175
}
2207-
handle->prev = handle->cur;
2208-
}
2209-
handle->buf_offset = handle->cur_offset;
2210-
if (handle->cur_offset + count >= PAGE_SIZE) {
2211-
count = PAGE_SIZE - handle->cur_offset;
2212-
handle->cur_offset = 0;
2213-
handle->cur++;
22142176
} else {
2215-
handle->cur_offset += count;
2177+
copy_last_highmem_page();
2178+
handle->buffer = get_buffer(&orig_bm, &ca);
2179+
if (IS_ERR(handle->buffer))
2180+
return PTR_ERR(handle->buffer);
2181+
if (handle->buffer != buffer)
2182+
handle->sync_read = 0;
22162183
}
2217-
handle->offset += count;
2218-
return count;
2184+
handle->cur++;
2185+
return PAGE_SIZE;
22192186
}
22202187

22212188
/**
@@ -2230,7 +2197,7 @@ void snapshot_write_finalize(struct snapshot_handle *handle)
22302197
{
22312198
copy_last_highmem_page();
22322199
/* Free only if we have loaded the image entirely */
2233-
if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) {
2200+
if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
22342201
memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);
22352202
free_highmem_data();
22362203
}

kernel/power/swap.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ static int save_image(struct swap_map_handle *handle,
431431
bio = NULL;
432432
do_gettimeofday(&start);
433433
while (1) {
434-
ret = snapshot_read_next(snapshot, PAGE_SIZE);
434+
ret = snapshot_read_next(snapshot);
435435
if (ret <= 0)
436436
break;
437437
ret = swap_write_page(handle, data_of(*snapshot), &bio);
@@ -492,7 +492,7 @@ int swsusp_write(unsigned int flags)
492492
return error;
493493
}
494494
memset(&snapshot, 0, sizeof(struct snapshot_handle));
495-
error = snapshot_read_next(&snapshot, PAGE_SIZE);
495+
error = snapshot_read_next(&snapshot);
496496
if (error < PAGE_SIZE) {
497497
if (error >= 0)
498498
error = -EFAULT;
@@ -615,7 +615,7 @@ static int load_image(struct swap_map_handle *handle,
615615
bio = NULL;
616616
do_gettimeofday(&start);
617617
for ( ; ; ) {
618-
error = snapshot_write_next(snapshot, PAGE_SIZE);
618+
error = snapshot_write_next(snapshot);
619619
if (error <= 0)
620620
break;
621621
error = swap_read_page(handle, data_of(*snapshot), &bio);
@@ -660,7 +660,7 @@ int swsusp_read(unsigned int *flags_p)
660660
*flags_p = swsusp_header->flags;
661661

662662
memset(&snapshot, 0, sizeof(struct snapshot_handle));
663-
error = snapshot_write_next(&snapshot, PAGE_SIZE);
663+
error = snapshot_write_next(&snapshot);
664664
if (error < PAGE_SIZE)
665665
return error < 0 ? error : -EFAULT;
666666
header = (struct swsusp_info *)data_of(snapshot);

kernel/power/user.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf,
151151
{
152152
struct snapshot_data *data;
153153
ssize_t res;
154+
loff_t pg_offp = *offp & ~PAGE_MASK;
154155

155156
mutex_lock(&pm_mutex);
156157

@@ -159,14 +160,19 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf,
159160
res = -ENODATA;
160161
goto Unlock;
161162
}
162-
res = snapshot_read_next(&data->handle, count);
163-
if (res > 0) {
164-
if (copy_to_user(buf, data_of(data->handle), res))
165-
res = -EFAULT;
166-
else
167-
*offp = data->handle.offset;
163+
if (!pg_offp) { /* on page boundary? */
164+
res = snapshot_read_next(&data->handle);
165+
if (res <= 0)
166+
goto Unlock;
167+
} else {
168+
res = PAGE_SIZE - pg_offp;
168169
}
169170

171+
res = simple_read_from_buffer(buf, count, &pg_offp,
172+
data_of(data->handle), res);
173+
if (res > 0)
174+
*offp += res;
175+
170176
Unlock:
171177
mutex_unlock(&pm_mutex);
172178

@@ -178,18 +184,25 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
178184
{
179185
struct snapshot_data *data;
180186
ssize_t res;
187+
loff_t pg_offp = *offp & ~PAGE_MASK;
181188

182189
mutex_lock(&pm_mutex);
183190

184191
data = filp->private_data;
185-
res = snapshot_write_next(&data->handle, count);
186-
if (res > 0) {
187-
if (copy_from_user(data_of(data->handle), buf, res))
188-
res = -EFAULT;
189-
else
190-
*offp = data->handle.offset;
192+
193+
if (!pg_offp) {
194+
res = snapshot_write_next(&data->handle);
195+
if (res <= 0)
196+
goto unlock;
197+
} else {
198+
res = PAGE_SIZE - pg_offp;
191199
}
192200

201+
res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
202+
buf, count);
203+
if (res > 0)
204+
*offp += res;
205+
unlock:
193206
mutex_unlock(&pm_mutex);
194207

195208
return res;

0 commit comments

Comments
 (0)