Annotation of /trunk/kernel26-alx/patches-2.6.27-r3/0146-2.6.27.47-all-fixes.patch
Parent Directory | Revision Log
Revision 1176 -
(hide annotations)
(download)
Thu Oct 14 15:11:06 2010 UTC (13 years, 11 months ago) by niro
File size: 49366 byte(s)
Thu Oct 14 15:11:06 2010 UTC (13 years, 11 months ago) by niro
File size: 49366 byte(s)
-2.6.27-alx-r3: new magellan 0.5.2 kernel
1 | niro | 1176 | diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c |
2 | index 876e918..f459e3e 100644 | ||
3 | --- a/arch/x86/kernel/process.c | ||
4 | +++ b/arch/x86/kernel/process.c | ||
5 | @@ -283,16 +283,12 @@ static void c1e_idle(void) | ||
6 | if (!cpu_isset(cpu, c1e_mask)) { | ||
7 | cpu_set(cpu, c1e_mask); | ||
8 | /* | ||
9 | - * Force broadcast so ACPI can not interfere. Needs | ||
10 | - * to run with interrupts enabled as it uses | ||
11 | - * smp_function_call. | ||
12 | + * Force broadcast so ACPI can not interfere. | ||
13 | */ | ||
14 | - local_irq_enable(); | ||
15 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, | ||
16 | &cpu); | ||
17 | printk(KERN_INFO "Switch to broadcast mode on CPU%d\n", | ||
18 | cpu); | ||
19 | - local_irq_disable(); | ||
20 | } | ||
21 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); | ||
22 | |||
23 | diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c | ||
24 | index 5639e27..94483a2 100644 | ||
25 | --- a/drivers/acpi/processor_idle.c | ||
26 | +++ b/drivers/acpi/processor_idle.c | ||
27 | @@ -317,8 +317,9 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, | ||
28 | pr->power.timer_broadcast_on_state = state; | ||
29 | } | ||
30 | |||
31 | -static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | ||
32 | +static void __lapic_timer_propagate_broadcast(void *arg) | ||
33 | { | ||
34 | + struct acpi_processor *pr = (struct acpi_processor *) arg; | ||
35 | unsigned long reason; | ||
36 | |||
37 | reason = pr->power.timer_broadcast_on_state < INT_MAX ? | ||
38 | @@ -327,6 +328,12 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | ||
39 | clockevents_notify(reason, &pr->id); | ||
40 | } | ||
41 | |||
42 | +static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) | ||
43 | +{ | ||
44 | + smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast, | ||
45 | + (void *)pr, 1); | ||
46 | +} | ||
47 | + | ||
48 | /* Power(C) State timer broadcast control */ | ||
49 | static void acpi_state_timer_broadcast(struct acpi_processor *pr, | ||
50 | struct acpi_processor_cx *cx, | ||
51 | @@ -347,7 +354,7 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | ||
52 | |||
53 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, | ||
54 | struct acpi_processor_cx *cstate) { } | ||
55 | -static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } | ||
56 | +static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } | ||
57 | static void acpi_state_timer_broadcast(struct acpi_processor *pr, | ||
58 | struct acpi_processor_cx *cx, | ||
59 | int broadcast) | ||
60 | @@ -1177,7 +1184,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | ||
61 | working++; | ||
62 | } | ||
63 | |||
64 | - acpi_propagate_timer_broadcast(pr); | ||
65 | + lapic_timer_propagate_broadcast(pr); | ||
66 | |||
67 | return (working); | ||
68 | } | ||
69 | diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c | ||
70 | index 22995d7..9358fa6 100644 | ||
71 | --- a/drivers/ata/libata-eh.c | ||
72 | +++ b/drivers/ata/libata-eh.c | ||
73 | @@ -1497,6 +1497,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) | ||
74 | } | ||
75 | |||
76 | /* okay, this error is ours */ | ||
77 | + memset(&tf, 0, sizeof(tf)); | ||
78 | rc = ata_eh_read_log_10h(dev, &tag, &tf); | ||
79 | if (rc) { | ||
80 | ata_link_printk(link, KERN_ERR, "failed to read log page 10h " | ||
81 | @@ -1900,8 +1901,9 @@ static void ata_eh_link_autopsy(struct ata_link *link) | ||
82 | qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); | ||
83 | |||
84 | /* determine whether the command is worth retrying */ | ||
85 | - if (!(qc->err_mask & AC_ERR_INVALID) && | ||
86 | - ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV)) | ||
87 | + if (qc->flags & ATA_QCFLAG_IO || | ||
88 | + (!(qc->err_mask & AC_ERR_INVALID) && | ||
89 | + qc->err_mask != AC_ERR_DEV)) | ||
90 | qc->flags |= ATA_QCFLAG_RETRY; | ||
91 | |||
92 | /* accumulate error info */ | ||
93 | diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c | ||
94 | index e6788f4..f325128 100644 | ||
95 | --- a/drivers/char/tty_io.c | ||
96 | +++ b/drivers/char/tty_io.c | ||
97 | @@ -1893,6 +1893,8 @@ static void release_one_tty(struct tty_struct *tty, int idx) | ||
98 | list_del_init(&tty->tty_files); | ||
99 | file_list_unlock(); | ||
100 | |||
101 | + put_pid(tty->pgrp); | ||
102 | + put_pid(tty->session); | ||
103 | free_tty_struct(tty); | ||
104 | } | ||
105 | |||
106 | diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c | ||
107 | index f942ecd..0af9a2c 100644 | ||
108 | --- a/drivers/hwmon/w83781d.c | ||
109 | +++ b/drivers/hwmon/w83781d.c | ||
110 | @@ -1797,17 +1797,17 @@ static int __init | ||
111 | w83781d_isa_found(unsigned short address) | ||
112 | { | ||
113 | int val, save, found = 0; | ||
114 | - | ||
115 | - /* We have to request the region in two parts because some | ||
116 | - boards declare base+4 to base+7 as a PNP device */ | ||
117 | - if (!request_region(address, 4, "w83781d")) { | ||
118 | - pr_debug("w83781d: Failed to request low part of region\n"); | ||
119 | - return 0; | ||
120 | - } | ||
121 | - if (!request_region(address + 4, 4, "w83781d")) { | ||
122 | - pr_debug("w83781d: Failed to request high part of region\n"); | ||
123 | - release_region(address, 4); | ||
124 | - return 0; | ||
125 | + int port; | ||
126 | + | ||
127 | + /* Some boards declare base+0 to base+7 as a PNP device, some base+4 | ||
128 | + * to base+7 and some base+5 to base+6. So we better request each port | ||
129 | + * individually for the probing phase. */ | ||
130 | + for (port = address; port < address + W83781D_EXTENT; port++) { | ||
131 | + if (!request_region(port, 1, "w83781d")) { | ||
132 | + pr_debug("w83781d: Failed to request port 0x%x\n", | ||
133 | + port); | ||
134 | + goto release; | ||
135 | + } | ||
136 | } | ||
137 | |||
138 | #define REALLY_SLOW_IO | ||
139 | @@ -1881,8 +1881,8 @@ w83781d_isa_found(unsigned short address) | ||
140 | val == 0x30 ? "W83782D" : "W83781D", (int)address); | ||
141 | |||
142 | release: | ||
143 | - release_region(address + 4, 4); | ||
144 | - release_region(address, 4); | ||
145 | + for (port--; port >= address; port--) | ||
146 | + release_region(port, 1); | ||
147 | return found; | ||
148 | } | ||
149 | |||
150 | diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c | ||
151 | index dc7ea32..177346e 100644 | ||
152 | --- a/drivers/i2c/busses/i2c-i801.c | ||
153 | +++ b/drivers/i2c/busses/i2c-i801.c | ||
154 | @@ -413,9 +413,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | ||
155 | data->block[0] = 32; /* max for SMBus block reads */ | ||
156 | } | ||
157 | |||
158 | + /* Experience has shown that the block buffer can only be used for | ||
159 | + SMBus (not I2C) block transactions, even though the datasheet | ||
160 | + doesn't mention this limitation. */ | ||
161 | if ((i801_features & FEATURE_BLOCK_BUFFER) | ||
162 | - && !(command == I2C_SMBUS_I2C_BLOCK_DATA | ||
163 | - && read_write == I2C_SMBUS_READ) | ||
164 | + && command != I2C_SMBUS_I2C_BLOCK_DATA | ||
165 | && i801_set_block_buffer_mode() == 0) | ||
166 | result = i801_block_transaction_by_block(data, read_write, | ||
167 | hwpec); | ||
168 | diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c | ||
169 | index b1c050f..e29b6d5 100644 | ||
170 | --- a/drivers/i2c/busses/i2c-tiny-usb.c | ||
171 | +++ b/drivers/i2c/busses/i2c-tiny-usb.c | ||
172 | @@ -13,6 +13,7 @@ | ||
173 | #include <linux/kernel.h> | ||
174 | #include <linux/errno.h> | ||
175 | #include <linux/module.h> | ||
176 | +#include <linux/types.h> | ||
177 | |||
178 | /* include interfaces to usb layer */ | ||
179 | #include <linux/usb.h> | ||
180 | @@ -31,8 +32,8 @@ | ||
181 | #define CMD_I2C_IO_END (1<<1) | ||
182 | |||
183 | /* i2c bit delay, default is 10us -> 100kHz */ | ||
184 | -static int delay = 10; | ||
185 | -module_param(delay, int, 0); | ||
186 | +static unsigned short delay = 10; | ||
187 | +module_param(delay, ushort, 0); | ||
188 | MODULE_PARM_DESC(delay, "bit delay in microseconds, " | ||
189 | "e.g. 10 for 100kHz (default is 100kHz)"); | ||
190 | |||
191 | @@ -109,7 +110,7 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) | ||
192 | |||
193 | static u32 usb_func(struct i2c_adapter *adapter) | ||
194 | { | ||
195 | - u32 func; | ||
196 | + __le32 func; | ||
197 | |||
198 | /* get functionality from adapter */ | ||
199 | if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != | ||
200 | @@ -118,7 +119,7 @@ static u32 usb_func(struct i2c_adapter *adapter) | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | - return func; | ||
205 | + return le32_to_cpu(func); | ||
206 | } | ||
207 | |||
208 | /* This is the actual algorithm we define */ | ||
209 | @@ -216,8 +217,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, | ||
210 | "i2c-tiny-usb at bus %03d device %03d", | ||
211 | dev->usb_dev->bus->busnum, dev->usb_dev->devnum); | ||
212 | |||
213 | - if (usb_write(&dev->adapter, CMD_SET_DELAY, | ||
214 | - cpu_to_le16(delay), 0, NULL, 0) != 0) { | ||
215 | + if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) { | ||
216 | dev_err(&dev->adapter.dev, | ||
217 | "failure setting delay to %dus\n", delay); | ||
218 | retval = -EIO; | ||
219 | diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c | ||
220 | index 3d3fb00..5ba06d9 100644 | ||
221 | --- a/drivers/i2c/i2c-core.c | ||
222 | +++ b/drivers/i2c/i2c-core.c | ||
223 | @@ -1269,14 +1269,24 @@ static int i2c_detect_address(struct i2c_client *temp_client, int kind, | ||
224 | |||
225 | /* Make sure there is something at this address, unless forced */ | ||
226 | if (kind < 0) { | ||
227 | - if (i2c_smbus_xfer(adapter, addr, 0, 0, 0, | ||
228 | - I2C_SMBUS_QUICK, NULL) < 0) | ||
229 | - return 0; | ||
230 | + if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) { | ||
231 | + /* Special probe for FSC hwmon chips */ | ||
232 | + union i2c_smbus_data dummy; | ||
233 | |||
234 | - /* prevent 24RF08 corruption */ | ||
235 | - if ((addr & ~0x0f) == 0x50) | ||
236 | - i2c_smbus_xfer(adapter, addr, 0, 0, 0, | ||
237 | - I2C_SMBUS_QUICK, NULL); | ||
238 | + if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0, | ||
239 | + I2C_SMBUS_BYTE_DATA, &dummy) < 0) | ||
240 | + return 0; | ||
241 | + } else { | ||
242 | + if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0, | ||
243 | + I2C_SMBUS_QUICK, NULL) < 0) | ||
244 | + return 0; | ||
245 | + | ||
246 | + /* Prevent 24RF08 corruption */ | ||
247 | + if ((addr & ~0x0f) == 0x50) | ||
248 | + i2c_smbus_xfer(adapter, addr, 0, | ||
249 | + I2C_SMBUS_WRITE, 0, | ||
250 | + I2C_SMBUS_QUICK, NULL); | ||
251 | + } | ||
252 | } | ||
253 | |||
254 | /* Finally call the custom detection function */ | ||
255 | diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c | ||
256 | index 4c3f124..342df4a 100644 | ||
257 | --- a/drivers/scsi/megaraid/megaraid_sas.c | ||
258 | +++ b/drivers/scsi/megaraid/megaraid_sas.c | ||
259 | @@ -3292,6 +3292,7 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | ||
260 | compat_alloc_user_space(sizeof(struct megasas_iocpacket)); | ||
261 | int i; | ||
262 | int error = 0; | ||
263 | + compat_uptr_t ptr; | ||
264 | |||
265 | if (clear_user(ioc, sizeof(*ioc))) | ||
266 | return -EFAULT; | ||
267 | @@ -3304,9 +3305,22 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | ||
268 | copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) | ||
269 | return -EFAULT; | ||
270 | |||
271 | - for (i = 0; i < MAX_IOCTL_SGE; i++) { | ||
272 | - compat_uptr_t ptr; | ||
273 | + /* | ||
274 | + * The sense_ptr is used in megasas_mgmt_fw_ioctl only when | ||
275 | + * sense_len is not null, so prepare the 64bit value under | ||
276 | + * the same condition. | ||
277 | + */ | ||
278 | + if (ioc->sense_len) { | ||
279 | + void __user **sense_ioc_ptr = | ||
280 | + (void __user **)(ioc->frame.raw + ioc->sense_off); | ||
281 | + compat_uptr_t *sense_cioc_ptr = | ||
282 | + (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); | ||
283 | + if (get_user(ptr, sense_cioc_ptr) || | ||
284 | + put_user(compat_ptr(ptr), sense_ioc_ptr)) | ||
285 | + return -EFAULT; | ||
286 | + } | ||
287 | |||
288 | + for (i = 0; i < MAX_IOCTL_SGE; i++) { | ||
289 | if (get_user(ptr, &cioc->sgl[i].iov_base) || | ||
290 | put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || | ||
291 | copy_in_user(&ioc->sgl[i].iov_len, | ||
292 | diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c | ||
293 | index 83887ff..2c3cdbd 100644 | ||
294 | --- a/drivers/usb/core/inode.c | ||
295 | +++ b/drivers/usb/core/inode.c | ||
296 | @@ -510,13 +510,13 @@ static int fs_create_by_name (const char *name, mode_t mode, | ||
297 | *dentry = NULL; | ||
298 | mutex_lock(&parent->d_inode->i_mutex); | ||
299 | *dentry = lookup_one_len(name, parent, strlen(name)); | ||
300 | - if (!IS_ERR(dentry)) { | ||
301 | + if (!IS_ERR(*dentry)) { | ||
302 | if ((mode & S_IFMT) == S_IFDIR) | ||
303 | error = usbfs_mkdir (parent->d_inode, *dentry, mode); | ||
304 | else | ||
305 | error = usbfs_create (parent->d_inode, *dentry, mode); | ||
306 | } else | ||
307 | - error = PTR_ERR(dentry); | ||
308 | + error = PTR_ERR(*dentry); | ||
309 | mutex_unlock(&parent->d_inode->i_mutex); | ||
310 | |||
311 | return error; | ||
312 | diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c | ||
313 | index 8b7c776..532f8cc 100644 | ||
314 | --- a/fs/ext4/balloc.c | ||
315 | +++ b/fs/ext4/balloc.c | ||
316 | @@ -1754,6 +1754,44 @@ out: | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | +int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | ||
321 | + ext4_fsblk_t nblocks) | ||
322 | +{ | ||
323 | + s64 free_blocks, dirty_blocks; | ||
324 | + ext4_fsblk_t root_blocks = 0; | ||
325 | + struct percpu_counter *fbc = &sbi->s_freeblocks_counter; | ||
326 | + struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; | ||
327 | + | ||
328 | + free_blocks = percpu_counter_read_positive(fbc); | ||
329 | + dirty_blocks = percpu_counter_read_positive(dbc); | ||
330 | + | ||
331 | + if (!capable(CAP_SYS_RESOURCE) && | ||
332 | + sbi->s_resuid != current->fsuid && | ||
333 | + (sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid))) | ||
334 | + root_blocks = ext4_r_blocks_count(sbi->s_es); | ||
335 | + | ||
336 | + if (free_blocks - (nblocks + root_blocks + dirty_blocks) < | ||
337 | + EXT4_FREEBLOCKS_WATERMARK) { | ||
338 | + free_blocks = percpu_counter_sum(fbc); | ||
339 | + dirty_blocks = percpu_counter_sum(dbc); | ||
340 | + if (dirty_blocks < 0) { | ||
341 | + printk(KERN_CRIT "Dirty block accounting " | ||
342 | + "went wrong %lld\n", | ||
343 | + dirty_blocks); | ||
344 | + } | ||
345 | + } | ||
346 | + /* Check whether we have space after | ||
347 | + * accounting for current dirty blocks | ||
348 | + */ | ||
349 | + if (free_blocks < ((s64)(root_blocks + nblocks) + dirty_blocks)) | ||
350 | + /* we don't have free space */ | ||
351 | + return -ENOSPC; | ||
352 | + | ||
353 | + /* Add the blocks to nblocks */ | ||
354 | + percpu_counter_add(dbc, nblocks); | ||
355 | + return 0; | ||
356 | +} | ||
357 | + | ||
358 | /** | ||
359 | * ext4_has_free_blocks() | ||
360 | * @sbi: in-core super block structure. | ||
361 | @@ -1766,27 +1804,31 @@ out: | ||
362 | ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi, | ||
363 | ext4_fsblk_t nblocks) | ||
364 | { | ||
365 | - ext4_fsblk_t free_blocks; | ||
366 | + ext4_fsblk_t free_blocks, dirty_blocks; | ||
367 | ext4_fsblk_t root_blocks = 0; | ||
368 | + struct percpu_counter *fbc = &sbi->s_freeblocks_counter; | ||
369 | + struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; | ||
370 | |||
371 | - free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); | ||
372 | + free_blocks = percpu_counter_read_positive(fbc); | ||
373 | + dirty_blocks = percpu_counter_read_positive(dbc); | ||
374 | |||
375 | if (!capable(CAP_SYS_RESOURCE) && | ||
376 | sbi->s_resuid != current->fsuid && | ||
377 | (sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid))) | ||
378 | root_blocks = ext4_r_blocks_count(sbi->s_es); | ||
379 | -#ifdef CONFIG_SMP | ||
380 | - if (free_blocks - root_blocks < FBC_BATCH) | ||
381 | - free_blocks = | ||
382 | - percpu_counter_sum_and_set(&sbi->s_freeblocks_counter); | ||
383 | -#endif | ||
384 | - if (free_blocks <= root_blocks) | ||
385 | + | ||
386 | + if (free_blocks - (nblocks + root_blocks + dirty_blocks) < | ||
387 | + EXT4_FREEBLOCKS_WATERMARK) { | ||
388 | + free_blocks = percpu_counter_sum_positive(fbc); | ||
389 | + dirty_blocks = percpu_counter_sum_positive(dbc); | ||
390 | + } | ||
391 | + if (free_blocks <= (root_blocks + dirty_blocks)) | ||
392 | /* we don't have free space */ | ||
393 | return 0; | ||
394 | - if (free_blocks - root_blocks < nblocks) | ||
395 | + if (free_blocks - (root_blocks + dirty_blocks) < nblocks) | ||
396 | return free_blocks - root_blocks; | ||
397 | return nblocks; | ||
398 | - } | ||
399 | +} | ||
400 | |||
401 | |||
402 | /** | ||
403 | @@ -1865,14 +1907,17 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode, | ||
404 | /* | ||
405 | * With delalloc we already reserved the blocks | ||
406 | */ | ||
407 | - *count = ext4_has_free_blocks(sbi, *count); | ||
408 | - } | ||
409 | - if (*count == 0) { | ||
410 | - *errp = -ENOSPC; | ||
411 | - return 0; /*return with ENOSPC error */ | ||
412 | + while (*count && ext4_claim_free_blocks(sbi, *count)) { | ||
413 | + /* let others to free the space */ | ||
414 | + yield(); | ||
415 | + *count = *count >> 1; | ||
416 | + } | ||
417 | + if (!*count) { | ||
418 | + *errp = -ENOSPC; | ||
419 | + return 0; /*return with ENOSPC error */ | ||
420 | + } | ||
421 | + num = *count; | ||
422 | } | ||
423 | - num = *count; | ||
424 | - | ||
425 | /* | ||
426 | * Check quota for allocation of this block. | ||
427 | */ | ||
428 | @@ -2067,9 +2112,14 @@ allocated: | ||
429 | le16_add_cpu(&gdp->bg_free_blocks_count, -num); | ||
430 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp); | ||
431 | spin_unlock(sb_bgl_lock(sbi, group_no)); | ||
432 | + percpu_counter_sub(&sbi->s_freeblocks_counter, num); | ||
433 | + /* | ||
434 | + * Now reduce the dirty block count also. Should not go negative | ||
435 | + */ | ||
436 | if (!EXT4_I(inode)->i_delalloc_reserved_flag) | ||
437 | - percpu_counter_sub(&sbi->s_freeblocks_counter, num); | ||
438 | - | ||
439 | + percpu_counter_sub(&sbi->s_dirtyblocks_counter, *count); | ||
440 | + else | ||
441 | + percpu_counter_sub(&sbi->s_dirtyblocks_counter, num); | ||
442 | if (sbi->s_log_groups_per_flex) { | ||
443 | ext4_group_t flex_group = ext4_flex_group(sbi, group_no); | ||
444 | spin_lock(sb_bgl_lock(sbi, flex_group)); | ||
445 | diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h | ||
446 | index 1985721..7b666b2 100644 | ||
447 | --- a/fs/ext4/ext4.h | ||
448 | +++ b/fs/ext4/ext4.h | ||
449 | @@ -1015,6 +1015,8 @@ extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, | ||
450 | unsigned long *count, int *errp); | ||
451 | extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode, | ||
452 | ext4_fsblk_t goal, unsigned long *count, int *errp); | ||
453 | +extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | ||
454 | + ext4_fsblk_t nblocks); | ||
455 | extern ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi, | ||
456 | ext4_fsblk_t nblocks); | ||
457 | extern void ext4_free_blocks (handle_t *handle, struct inode *inode, | ||
458 | @@ -1245,6 +1247,17 @@ do { \ | ||
459 | __ext4_std_error((sb), __func__, (errno)); \ | ||
460 | } while (0) | ||
461 | |||
462 | +#ifdef CONFIG_SMP | ||
463 | +/* Each CPU can accumulate FBC_BATCH blocks in their local | ||
464 | + * counters. So we need to make sure we have free blocks more | ||
465 | + * than FBC_BATCH * nr_cpu_ids. Also add a window of 4 times. | ||
466 | + */ | ||
467 | +#define EXT4_FREEBLOCKS_WATERMARK (4 * (FBC_BATCH * nr_cpu_ids)) | ||
468 | +#else | ||
469 | +#define EXT4_FREEBLOCKS_WATERMARK 0 | ||
470 | +#endif | ||
471 | + | ||
472 | + | ||
473 | /* | ||
474 | * Inodes and files operations | ||
475 | */ | ||
476 | diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h | ||
477 | index f20df8a..6d096d5 100644 | ||
478 | --- a/fs/ext4/ext4_sb.h | ||
479 | +++ b/fs/ext4/ext4_sb.h | ||
480 | @@ -60,6 +60,7 @@ struct ext4_sb_info { | ||
481 | struct percpu_counter s_freeblocks_counter; | ||
482 | struct percpu_counter s_freeinodes_counter; | ||
483 | struct percpu_counter s_dirs_counter; | ||
484 | + struct percpu_counter s_dirtyblocks_counter; | ||
485 | struct blockgroup_lock s_blockgroup_lock; | ||
486 | |||
487 | /* root of the per fs reservation window tree */ | ||
488 | diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c | ||
489 | index aeebfc2..a67f837 100644 | ||
490 | --- a/fs/ext4/inode.c | ||
491 | +++ b/fs/ext4/inode.c | ||
492 | @@ -1032,19 +1032,20 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used) | ||
493 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | ||
494 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; | ||
495 | |||
496 | - /* Account for allocated meta_blocks */ | ||
497 | - mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks; | ||
498 | - | ||
499 | - /* update fs free blocks counter for truncate case */ | ||
500 | - percpu_counter_add(&sbi->s_freeblocks_counter, mdb_free); | ||
501 | + if (mdb_free) { | ||
502 | + /* Account for allocated meta_blocks */ | ||
503 | + mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks; | ||
504 | + | ||
505 | + /* update fs dirty blocks counter */ | ||
506 | + percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free); | ||
507 | + EXT4_I(inode)->i_allocated_meta_blocks = 0; | ||
508 | + EXT4_I(inode)->i_reserved_meta_blocks = mdb; | ||
509 | + } | ||
510 | |||
511 | /* update per-inode reservations */ | ||
512 | BUG_ON(used > EXT4_I(inode)->i_reserved_data_blocks); | ||
513 | EXT4_I(inode)->i_reserved_data_blocks -= used; | ||
514 | |||
515 | - BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | ||
516 | - EXT4_I(inode)->i_reserved_meta_blocks = mdb; | ||
517 | - EXT4_I(inode)->i_allocated_meta_blocks = 0; | ||
518 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
519 | |||
520 | /* | ||
521 | @@ -1548,6 +1549,7 @@ static int ext4_journalled_write_end(struct file *file, | ||
522 | |||
523 | static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | ||
524 | { | ||
525 | + int retries = 0; | ||
526 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
527 | unsigned long md_needed, mdblocks, total = 0; | ||
528 | |||
529 | @@ -1556,6 +1558,7 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | ||
530 | * in order to allocate nrblocks | ||
531 | * worse case is one extent per block | ||
532 | */ | ||
533 | +repeat: | ||
534 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | ||
535 | total = EXT4_I(inode)->i_reserved_data_blocks + nrblocks; | ||
536 | mdblocks = ext4_calc_metadata_amount(inode, total); | ||
537 | @@ -1564,13 +1567,14 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | ||
538 | md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks; | ||
539 | total = md_needed + nrblocks; | ||
540 | |||
541 | - if (ext4_has_free_blocks(sbi, total) < total) { | ||
542 | + if (ext4_claim_free_blocks(sbi, total)) { | ||
543 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
544 | + if (ext4_should_retry_alloc(inode->i_sb, &retries)) { | ||
545 | + yield(); | ||
546 | + goto repeat; | ||
547 | + } | ||
548 | return -ENOSPC; | ||
549 | } | ||
550 | - /* reduce fs free blocks counter */ | ||
551 | - percpu_counter_sub(&sbi->s_freeblocks_counter, total); | ||
552 | - | ||
553 | EXT4_I(inode)->i_reserved_data_blocks += nrblocks; | ||
554 | EXT4_I(inode)->i_reserved_meta_blocks = mdblocks; | ||
555 | |||
556 | @@ -1612,8 +1616,8 @@ static void ext4_da_release_space(struct inode *inode, int to_free) | ||
557 | |||
558 | release = to_free + mdb_free; | ||
559 | |||
560 | - /* update fs free blocks counter for truncate case */ | ||
561 | - percpu_counter_add(&sbi->s_freeblocks_counter, release); | ||
562 | + /* update fs dirty blocks counter for truncate case */ | ||
563 | + percpu_counter_sub(&sbi->s_dirtyblocks_counter, release); | ||
564 | |||
565 | /* update per-inode reservations */ | ||
566 | BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks); | ||
567 | @@ -1657,6 +1661,7 @@ struct mpage_da_data { | ||
568 | struct writeback_control *wbc; | ||
569 | int io_done; | ||
570 | long pages_written; | ||
571 | + int retval; | ||
572 | }; | ||
573 | |||
574 | /* | ||
575 | @@ -1694,17 +1699,23 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) | ||
576 | |||
577 | pagevec_init(&pvec, 0); | ||
578 | while (index <= end) { | ||
579 | - nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); | ||
580 | + /* | ||
581 | + * We can use PAGECACHE_TAG_DIRTY lookup here because | ||
582 | + * even though we have cleared the dirty flag on the page | ||
583 | + * We still keep the page in the radix tree with tag | ||
584 | + * PAGECACHE_TAG_DIRTY. See clear_page_dirty_for_io. | ||
585 | + * The PAGECACHE_TAG_DIRTY is cleared in set_page_writeback | ||
586 | + * which is called via the below writepage callback. | ||
587 | + */ | ||
588 | + nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, | ||
589 | + PAGECACHE_TAG_DIRTY, | ||
590 | + min(end - index, | ||
591 | + (pgoff_t)PAGEVEC_SIZE-1) + 1); | ||
592 | if (nr_pages == 0) | ||
593 | break; | ||
594 | for (i = 0; i < nr_pages; i++) { | ||
595 | struct page *page = pvec.pages[i]; | ||
596 | |||
597 | - index = page->index; | ||
598 | - if (index > end) | ||
599 | - break; | ||
600 | - index++; | ||
601 | - | ||
602 | BUG_ON(!PageLocked(page)); | ||
603 | BUG_ON(PageWriteback(page)); | ||
604 | |||
605 | @@ -1821,6 +1832,57 @@ static inline void __unmap_underlying_blocks(struct inode *inode, | ||
606 | unmap_underlying_metadata(bdev, bh->b_blocknr + i); | ||
607 | } | ||
608 | |||
609 | +static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, | ||
610 | + sector_t logical, long blk_cnt) | ||
611 | +{ | ||
612 | + int nr_pages, i; | ||
613 | + pgoff_t index, end; | ||
614 | + struct pagevec pvec; | ||
615 | + struct inode *inode = mpd->inode; | ||
616 | + struct address_space *mapping = inode->i_mapping; | ||
617 | + | ||
618 | + index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
619 | + end = (logical + blk_cnt - 1) >> | ||
620 | + (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
621 | + while (index <= end) { | ||
622 | + nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); | ||
623 | + if (nr_pages == 0) | ||
624 | + break; | ||
625 | + for (i = 0; i < nr_pages; i++) { | ||
626 | + struct page *page = pvec.pages[i]; | ||
627 | + index = page->index; | ||
628 | + if (index > end) | ||
629 | + break; | ||
630 | + index++; | ||
631 | + | ||
632 | + BUG_ON(!PageLocked(page)); | ||
633 | + BUG_ON(PageWriteback(page)); | ||
634 | + block_invalidatepage(page, 0); | ||
635 | + ClearPageUptodate(page); | ||
636 | + unlock_page(page); | ||
637 | + } | ||
638 | + } | ||
639 | + return; | ||
640 | +} | ||
641 | + | ||
642 | +static void ext4_print_free_blocks(struct inode *inode) | ||
643 | +{ | ||
644 | + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
645 | + printk(KERN_EMERG "Total free blocks count %lld\n", | ||
646 | + ext4_count_free_blocks(inode->i_sb)); | ||
647 | + printk(KERN_EMERG "Free/Dirty block details\n"); | ||
648 | + printk(KERN_EMERG "free_blocks=%lld\n", | ||
649 | + percpu_counter_sum(&sbi->s_freeblocks_counter)); | ||
650 | + printk(KERN_EMERG "dirty_blocks=%lld\n", | ||
651 | + percpu_counter_sum(&sbi->s_dirtyblocks_counter)); | ||
652 | + printk(KERN_EMERG "Block reservation details\n"); | ||
653 | + printk(KERN_EMERG "i_reserved_data_blocks=%lu\n", | ||
654 | + EXT4_I(inode)->i_reserved_data_blocks); | ||
655 | + printk(KERN_EMERG "i_reserved_meta_blocks=%lu\n", | ||
656 | + EXT4_I(inode)->i_reserved_meta_blocks); | ||
657 | + return; | ||
658 | +} | ||
659 | + | ||
660 | /* | ||
661 | * mpage_da_map_blocks - go through given space | ||
662 | * | ||
663 | @@ -1830,32 +1892,69 @@ static inline void __unmap_underlying_blocks(struct inode *inode, | ||
664 | * The function skips space we know is already mapped to disk blocks. | ||
665 | * | ||
666 | */ | ||
667 | -static void mpage_da_map_blocks(struct mpage_da_data *mpd) | ||
668 | +static int mpage_da_map_blocks(struct mpage_da_data *mpd) | ||
669 | { | ||
670 | int err = 0; | ||
671 | - struct buffer_head *lbh = &mpd->lbh; | ||
672 | - sector_t next = lbh->b_blocknr; | ||
673 | struct buffer_head new; | ||
674 | + struct buffer_head *lbh = &mpd->lbh; | ||
675 | + sector_t next; | ||
676 | |||
677 | /* | ||
678 | * We consider only non-mapped and non-allocated blocks | ||
679 | */ | ||
680 | if (buffer_mapped(lbh) && !buffer_delay(lbh)) | ||
681 | - return; | ||
682 | - | ||
683 | + return 0; | ||
684 | new.b_state = lbh->b_state; | ||
685 | new.b_blocknr = 0; | ||
686 | new.b_size = lbh->b_size; | ||
687 | - | ||
688 | + next = lbh->b_blocknr; | ||
689 | /* | ||
690 | * If we didn't accumulate anything | ||
691 | * to write simply return | ||
692 | */ | ||
693 | if (!new.b_size) | ||
694 | - return; | ||
695 | + return 0; | ||
696 | err = mpd->get_block(mpd->inode, next, &new, 1); | ||
697 | - if (err) | ||
698 | - return; | ||
699 | + if (err) { | ||
700 | + | ||
701 | + /* If get block returns with error | ||
702 | + * we simply return. Later writepage | ||
703 | + * will redirty the page and writepages | ||
704 | + * will find the dirty page again | ||
705 | + */ | ||
706 | + if (err == -EAGAIN) | ||
707 | + return 0; | ||
708 | + | ||
709 | + if (err == -ENOSPC && | ||
710 | + ext4_count_free_blocks(mpd->inode->i_sb)) { | ||
711 | + mpd->retval = err; | ||
712 | + return 0; | ||
713 | + } | ||
714 | + | ||
715 | + /* | ||
716 | + * get block failure will cause us | ||
717 | + * to loop in writepages. Because | ||
718 | + * a_ops->writepage won't be able to | ||
719 | + * make progress. The page will be redirtied | ||
720 | + * by writepage and writepages will again | ||
721 | + * try to write the same. | ||
722 | + */ | ||
723 | + printk(KERN_EMERG "%s block allocation failed for inode %lu " | ||
724 | + "at logical offset %llu with max blocks " | ||
725 | + "%zd with error %d\n", | ||
726 | + __func__, mpd->inode->i_ino, | ||
727 | + (unsigned long long)next, | ||
728 | + lbh->b_size >> mpd->inode->i_blkbits, err); | ||
729 | + printk(KERN_EMERG "This should not happen.!! " | ||
730 | + "Data will be lost\n"); | ||
731 | + if (err == -ENOSPC) { | ||
732 | + ext4_print_free_blocks(mpd->inode); | ||
733 | + } | ||
734 | + /* invlaidate all the pages */ | ||
735 | + ext4_da_block_invalidatepages(mpd, next, | ||
736 | + lbh->b_size >> mpd->inode->i_blkbits); | ||
737 | + return err; | ||
738 | + } | ||
739 | BUG_ON(new.b_size == 0); | ||
740 | |||
741 | if (buffer_new(&new)) | ||
742 | @@ -1868,7 +1967,7 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) | ||
743 | if (buffer_delay(lbh) || buffer_unwritten(lbh)) | ||
744 | mpage_put_bnr_to_bhs(mpd, next, &new); | ||
745 | |||
746 | - return; | ||
747 | + return 0; | ||
748 | } | ||
749 | |||
750 | #define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ | ||
751 | @@ -1937,8 +2036,8 @@ flush_it: | ||
752 | * We couldn't merge the block to our extent, so we | ||
753 | * need to flush current extent and start new one | ||
754 | */ | ||
755 | - mpage_da_map_blocks(mpd); | ||
756 | - mpage_da_submit_io(mpd); | ||
757 | + if (mpage_da_map_blocks(mpd) == 0) | ||
758 | + mpage_da_submit_io(mpd); | ||
759 | mpd->io_done = 1; | ||
760 | return; | ||
761 | } | ||
762 | @@ -1980,8 +2079,8 @@ static int __mpage_da_writepage(struct page *page, | ||
763 | * and start IO on them using writepage() | ||
764 | */ | ||
765 | if (mpd->next_page != mpd->first_page) { | ||
766 | - mpage_da_map_blocks(mpd); | ||
767 | - mpage_da_submit_io(mpd); | ||
768 | + if (mpage_da_map_blocks(mpd) == 0) | ||
769 | + mpage_da_submit_io(mpd); | ||
770 | /* | ||
771 | * skip rest of the page in the page_vec | ||
772 | */ | ||
773 | @@ -2074,39 +2173,36 @@ static int __mpage_da_writepage(struct page *page, | ||
774 | */ | ||
775 | static int mpage_da_writepages(struct address_space *mapping, | ||
776 | struct writeback_control *wbc, | ||
777 | - get_block_t get_block) | ||
778 | + struct mpage_da_data *mpd) | ||
779 | { | ||
780 | - struct mpage_da_data mpd; | ||
781 | long to_write; | ||
782 | int ret; | ||
783 | |||
784 | - if (!get_block) | ||
785 | + if (!mpd->get_block) | ||
786 | return generic_writepages(mapping, wbc); | ||
787 | |||
788 | - mpd.wbc = wbc; | ||
789 | - mpd.inode = mapping->host; | ||
790 | - mpd.lbh.b_size = 0; | ||
791 | - mpd.lbh.b_state = 0; | ||
792 | - mpd.lbh.b_blocknr = 0; | ||
793 | - mpd.first_page = 0; | ||
794 | - mpd.next_page = 0; | ||
795 | - mpd.get_block = get_block; | ||
796 | - mpd.io_done = 0; | ||
797 | - mpd.pages_written = 0; | ||
798 | + mpd->lbh.b_size = 0; | ||
799 | + mpd->lbh.b_state = 0; | ||
800 | + mpd->lbh.b_blocknr = 0; | ||
801 | + mpd->first_page = 0; | ||
802 | + mpd->next_page = 0; | ||
803 | + mpd->io_done = 0; | ||
804 | + mpd->pages_written = 0; | ||
805 | + mpd->retval = 0; | ||
806 | |||
807 | to_write = wbc->nr_to_write; | ||
808 | |||
809 | - ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, &mpd); | ||
810 | + ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, mpd); | ||
811 | |||
812 | /* | ||
813 | * Handle last extent of pages | ||
814 | */ | ||
815 | - if (!mpd.io_done && mpd.next_page != mpd.first_page) { | ||
816 | - mpage_da_map_blocks(&mpd); | ||
817 | - mpage_da_submit_io(&mpd); | ||
818 | + if (!mpd->io_done && mpd->next_page != mpd->first_page) { | ||
819 | + if (mpage_da_map_blocks(mpd) == 0) | ||
820 | + mpage_da_submit_io(mpd); | ||
821 | } | ||
822 | |||
823 | - wbc->nr_to_write = to_write - mpd.pages_written; | ||
824 | + wbc->nr_to_write = to_write - mpd->pages_written; | ||
825 | return ret; | ||
826 | } | ||
827 | |||
828 | @@ -2352,7 +2448,7 @@ static int ext4_da_writepages(struct address_space *mapping, | ||
829 | struct writeback_control *wbc) | ||
830 | { | ||
831 | handle_t *handle = NULL; | ||
832 | - loff_t range_start = 0; | ||
833 | + struct mpage_da_data mpd; | ||
834 | struct inode *inode = mapping->host; | ||
835 | int needed_blocks, ret = 0, nr_to_writebump = 0; | ||
836 | long to_write, pages_skipped = 0; | ||
837 | @@ -2390,16 +2486,12 @@ static int ext4_da_writepages(struct address_space *mapping, | ||
838 | wbc->nr_to_write = sbi->s_mb_stream_request; | ||
839 | } | ||
840 | |||
841 | - if (!wbc->range_cyclic) | ||
842 | - /* | ||
843 | - * If range_cyclic is not set force range_cont | ||
844 | - * and save the old writeback_index | ||
845 | - */ | ||
846 | - wbc->range_cont = 1; | ||
847 | |||
848 | - range_start = wbc->range_start; | ||
849 | pages_skipped = wbc->pages_skipped; | ||
850 | |||
851 | + mpd.wbc = wbc; | ||
852 | + mpd.inode = mapping->host; | ||
853 | + | ||
854 | restart_loop: | ||
855 | to_write = wbc->nr_to_write; | ||
856 | while (!ret && to_write > 0) { | ||
857 | @@ -2435,11 +2527,17 @@ restart_loop: | ||
858 | goto out_writepages; | ||
859 | } | ||
860 | } | ||
861 | - | ||
862 | to_write -= wbc->nr_to_write; | ||
863 | - ret = mpage_da_writepages(mapping, wbc, | ||
864 | - ext4_da_get_block_write); | ||
865 | + | ||
866 | + mpd.get_block = ext4_da_get_block_write; | ||
867 | + ret = mpage_da_writepages(mapping, wbc, &mpd); | ||
868 | + | ||
869 | ext4_journal_stop(handle); | ||
870 | + | ||
871 | + if (mpd.retval == -ENOSPC) | ||
872 | + jbd2_journal_force_commit_nested(sbi->s_journal); | ||
873 | + | ||
874 | + /* reset the retry count */ | ||
875 | if (ret == MPAGE_DA_EXTENT_TAIL) { | ||
876 | /* | ||
877 | * got one extent now try with | ||
878 | @@ -2459,9 +2557,8 @@ restart_loop: | ||
879 | wbc->nr_to_write = to_write; | ||
880 | } | ||
881 | |||
882 | - if (wbc->range_cont && (pages_skipped != wbc->pages_skipped)) { | ||
883 | + if (!wbc->range_cyclic && (pages_skipped != wbc->pages_skipped)) { | ||
884 | /* We skipped pages in this loop */ | ||
885 | - wbc->range_start = range_start; | ||
886 | wbc->nr_to_write = to_write + | ||
887 | wbc->pages_skipped - pages_skipped; | ||
888 | wbc->pages_skipped = pages_skipped; | ||
889 | @@ -2470,7 +2567,6 @@ restart_loop: | ||
890 | |||
891 | out_writepages: | ||
892 | wbc->nr_to_write = to_write - nr_to_writebump; | ||
893 | - wbc->range_start = range_start; | ||
894 | return ret; | ||
895 | } | ||
896 | |||
897 | @@ -2488,7 +2584,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | ||
898 | index = pos >> PAGE_CACHE_SHIFT; | ||
899 | from = pos & (PAGE_CACHE_SIZE - 1); | ||
900 | to = from + len; | ||
901 | - | ||
902 | retry: | ||
903 | /* | ||
904 | * With delayed allocation, we don't log the i_disksize update | ||
905 | diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c | ||
906 | index c7dc115..453589d 100644 | ||
907 | --- a/fs/ext4/mballoc.c | ||
908 | +++ b/fs/ext4/mballoc.c | ||
909 | @@ -3100,7 +3100,7 @@ void exit_ext4_mballoc(void) | ||
910 | */ | ||
911 | static noinline_for_stack int | ||
912 | ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | ||
913 | - handle_t *handle) | ||
914 | + handle_t *handle, unsigned long reserv_blks) | ||
915 | { | ||
916 | struct buffer_head *bitmap_bh = NULL; | ||
917 | struct ext4_super_block *es; | ||
918 | @@ -3188,15 +3188,16 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | ||
919 | le16_add_cpu(&gdp->bg_free_blocks_count, -ac->ac_b_ex.fe_len); | ||
920 | gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp); | ||
921 | spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group)); | ||
922 | - | ||
923 | + percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len); | ||
924 | /* | ||
925 | - * free blocks account has already be reduced/reserved | ||
926 | - * at write_begin() time for delayed allocation | ||
927 | - * do not double accounting | ||
928 | + * Now reduce the dirty block count also. Should not go negative | ||
929 | */ | ||
930 | if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED)) | ||
931 | - percpu_counter_sub(&sbi->s_freeblocks_counter, | ||
932 | - ac->ac_b_ex.fe_len); | ||
933 | + /* release all the reserved blocks if non delalloc */ | ||
934 | + percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks); | ||
935 | + else | ||
936 | + percpu_counter_sub(&sbi->s_dirtyblocks_counter, | ||
937 | + ac->ac_b_ex.fe_len); | ||
938 | |||
939 | if (sbi->s_log_groups_per_flex) { | ||
940 | ext4_group_t flex_group = ext4_flex_group(sbi, | ||
941 | @@ -4630,12 +4631,13 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed) | ||
942 | ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | ||
943 | struct ext4_allocation_request *ar, int *errp) | ||
944 | { | ||
945 | + int freed; | ||
946 | struct ext4_allocation_context *ac = NULL; | ||
947 | struct ext4_sb_info *sbi; | ||
948 | struct super_block *sb; | ||
949 | ext4_fsblk_t block = 0; | ||
950 | - int freed; | ||
951 | - int inquota; | ||
952 | + unsigned long inquota; | ||
953 | + unsigned long reserv_blks = 0; | ||
954 | |||
955 | sb = ar->inode->i_sb; | ||
956 | sbi = EXT4_SB(sb); | ||
957 | @@ -4649,14 +4651,17 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | ||
958 | /* | ||
959 | * With delalloc we already reserved the blocks | ||
960 | */ | ||
961 | - ar->len = ext4_has_free_blocks(sbi, ar->len); | ||
962 | - } | ||
963 | - | ||
964 | - if (ar->len == 0) { | ||
965 | - *errp = -ENOSPC; | ||
966 | - return 0; | ||
967 | + while (ar->len && ext4_claim_free_blocks(sbi, ar->len)) { | ||
968 | + /* let others to free the space */ | ||
969 | + yield(); | ||
970 | + ar->len = ar->len >> 1; | ||
971 | + } | ||
972 | + if (!ar->len) { | ||
973 | + *errp = -ENOSPC; | ||
974 | + return 0; | ||
975 | + } | ||
976 | + reserv_blks = ar->len; | ||
977 | } | ||
978 | - | ||
979 | while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) { | ||
980 | ar->flags |= EXT4_MB_HINT_NOPREALLOC; | ||
981 | ar->len--; | ||
982 | @@ -4701,7 +4706,7 @@ repeat: | ||
983 | ext4_mb_new_preallocation(ac); | ||
984 | } | ||
985 | if (likely(ac->ac_status == AC_STATUS_FOUND)) { | ||
986 | - *errp = ext4_mb_mark_diskspace_used(ac, handle); | ||
987 | + *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks); | ||
988 | if (*errp == -EAGAIN) { | ||
989 | /* | ||
990 | * drop the reference that we took | ||
991 | diff --git a/fs/ext4/super.c b/fs/ext4/super.c | ||
992 | index baacaf8..2bca22d 100644 | ||
993 | --- a/fs/ext4/super.c | ||
994 | +++ b/fs/ext4/super.c | ||
995 | @@ -521,6 +521,7 @@ static void ext4_put_super(struct super_block *sb) | ||
996 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | ||
997 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
998 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
999 | + percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
1000 | brelse(sbi->s_sbh); | ||
1001 | #ifdef CONFIG_QUOTA | ||
1002 | for (i = 0; i < MAXQUOTAS; i++) | ||
1003 | @@ -2280,6 +2281,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | ||
1004 | err = percpu_counter_init(&sbi->s_dirs_counter, | ||
1005 | ext4_count_dirs(sb)); | ||
1006 | } | ||
1007 | + if (!err) { | ||
1008 | + err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); | ||
1009 | + } | ||
1010 | if (err) { | ||
1011 | printk(KERN_ERR "EXT4-fs: insufficient memory\n"); | ||
1012 | goto failed_mount3; | ||
1013 | @@ -2517,6 +2521,7 @@ failed_mount3: | ||
1014 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | ||
1015 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
1016 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
1017 | + percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
1018 | failed_mount2: | ||
1019 | for (i = 0; i < db_count; i++) | ||
1020 | brelse(sbi->s_group_desc[i]); | ||
1021 | @@ -3208,7 +3213,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | ||
1022 | buf->f_type = EXT4_SUPER_MAGIC; | ||
1023 | buf->f_bsize = sb->s_blocksize; | ||
1024 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; | ||
1025 | - buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter); | ||
1026 | + buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - | ||
1027 | + percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); | ||
1028 | ext4_free_blocks_count_set(es, buf->f_bfree); | ||
1029 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | ||
1030 | if (buf->f_bfree < ext4_r_blocks_count(es)) | ||
1031 | diff --git a/fs/nfs/client.c b/fs/nfs/client.c | ||
1032 | index 9d6a0e4..710645c 100644 | ||
1033 | --- a/fs/nfs/client.c | ||
1034 | +++ b/fs/nfs/client.c | ||
1035 | @@ -826,6 +826,8 @@ out_error: | ||
1036 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | ||
1037 | { | ||
1038 | target->flags = source->flags; | ||
1039 | + target->rsize = source->rsize; | ||
1040 | + target->wsize = source->wsize; | ||
1041 | target->acregmin = source->acregmin; | ||
1042 | target->acregmax = source->acregmax; | ||
1043 | target->acdirmin = source->acdirmin; | ||
1044 | diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c | ||
1045 | index e195f67..ee7ed21 100644 | ||
1046 | --- a/fs/nfs/dir.c | ||
1047 | +++ b/fs/nfs/dir.c | ||
1048 | @@ -826,6 +826,8 @@ out_zap_parent: | ||
1049 | /* If we have submounts, don't unhash ! */ | ||
1050 | if (have_submounts(dentry)) | ||
1051 | goto out_valid; | ||
1052 | + if (dentry->d_flags & DCACHE_DISCONNECTED) | ||
1053 | + goto out_valid; | ||
1054 | shrink_dcache_parent(dentry); | ||
1055 | } | ||
1056 | d_drop(dentry); | ||
1057 | diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c | ||
1058 | index abffc90..6203c81 100644 | ||
1059 | --- a/fs/nfsd/nfs4xdr.c | ||
1060 | +++ b/fs/nfsd/nfs4xdr.c | ||
1061 | @@ -179,10 +179,10 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) | ||
1062 | argp->p = page_address(argp->pagelist[0]); | ||
1063 | argp->pagelist++; | ||
1064 | if (argp->pagelen < PAGE_SIZE) { | ||
1065 | - argp->end = p + (argp->pagelen>>2); | ||
1066 | + argp->end = argp->p + (argp->pagelen>>2); | ||
1067 | argp->pagelen = 0; | ||
1068 | } else { | ||
1069 | - argp->end = p + (PAGE_SIZE>>2); | ||
1070 | + argp->end = argp->p + (PAGE_SIZE>>2); | ||
1071 | argp->pagelen -= PAGE_SIZE; | ||
1072 | } | ||
1073 | memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); | ||
1074 | @@ -1115,10 +1115,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | ||
1075 | argp->p = page_address(argp->pagelist[0]); | ||
1076 | argp->pagelist++; | ||
1077 | if (argp->pagelen < PAGE_SIZE) { | ||
1078 | - argp->end = p + (argp->pagelen>>2); | ||
1079 | + argp->end = argp->p + (argp->pagelen>>2); | ||
1080 | argp->pagelen = 0; | ||
1081 | } else { | ||
1082 | - argp->end = p + (PAGE_SIZE>>2); | ||
1083 | + argp->end = argp->p + (PAGE_SIZE>>2); | ||
1084 | argp->pagelen -= PAGE_SIZE; | ||
1085 | } | ||
1086 | } | ||
1087 | diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h | ||
1088 | index 2083888..9007ccd 100644 | ||
1089 | --- a/include/linux/percpu_counter.h | ||
1090 | +++ b/include/linux/percpu_counter.h | ||
1091 | @@ -35,7 +35,7 @@ int percpu_counter_init_irq(struct percpu_counter *fbc, s64 amount); | ||
1092 | void percpu_counter_destroy(struct percpu_counter *fbc); | ||
1093 | void percpu_counter_set(struct percpu_counter *fbc, s64 amount); | ||
1094 | void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch); | ||
1095 | -s64 __percpu_counter_sum(struct percpu_counter *fbc, int set); | ||
1096 | +s64 __percpu_counter_sum(struct percpu_counter *fbc); | ||
1097 | |||
1098 | static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount) | ||
1099 | { | ||
1100 | @@ -44,19 +44,13 @@ static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount) | ||
1101 | |||
1102 | static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc) | ||
1103 | { | ||
1104 | - s64 ret = __percpu_counter_sum(fbc, 0); | ||
1105 | + s64 ret = __percpu_counter_sum(fbc); | ||
1106 | return ret < 0 ? 0 : ret; | ||
1107 | } | ||
1108 | |||
1109 | -static inline s64 percpu_counter_sum_and_set(struct percpu_counter *fbc) | ||
1110 | -{ | ||
1111 | - return __percpu_counter_sum(fbc, 1); | ||
1112 | -} | ||
1113 | - | ||
1114 | - | ||
1115 | static inline s64 percpu_counter_sum(struct percpu_counter *fbc) | ||
1116 | { | ||
1117 | - return __percpu_counter_sum(fbc, 0); | ||
1118 | + return __percpu_counter_sum(fbc); | ||
1119 | } | ||
1120 | |||
1121 | static inline s64 percpu_counter_read(struct percpu_counter *fbc) | ||
1122 | diff --git a/include/linux/security.h b/include/linux/security.h | ||
1123 | index 1638afd..0601e71 100644 | ||
1124 | --- a/include/linux/security.h | ||
1125 | +++ b/include/linux/security.h | ||
1126 | @@ -1590,6 +1590,7 @@ int security_syslog(int type); | ||
1127 | int security_settime(struct timespec *ts, struct timezone *tz); | ||
1128 | int security_vm_enough_memory(long pages); | ||
1129 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); | ||
1130 | +int security_vm_enough_memory_kern(long pages); | ||
1131 | int security_bprm_alloc(struct linux_binprm *bprm); | ||
1132 | void security_bprm_free(struct linux_binprm *bprm); | ||
1133 | void security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe); | ||
1134 | @@ -1822,14 +1823,23 @@ static inline int security_settime(struct timespec *ts, struct timezone *tz) | ||
1135 | |||
1136 | static inline int security_vm_enough_memory(long pages) | ||
1137 | { | ||
1138 | + WARN_ON(current->mm == NULL); | ||
1139 | return cap_vm_enough_memory(current->mm, pages); | ||
1140 | } | ||
1141 | |||
1142 | static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) | ||
1143 | { | ||
1144 | + WARN_ON(mm == NULL); | ||
1145 | return cap_vm_enough_memory(mm, pages); | ||
1146 | } | ||
1147 | |||
1148 | +static inline int security_vm_enough_memory_kern(long pages) | ||
1149 | +{ | ||
1150 | + /* If current->mm is a kernel thread then we will pass NULL, | ||
1151 | + for this specific case that is fine */ | ||
1152 | + return cap_vm_enough_memory(current->mm, pages); | ||
1153 | +} | ||
1154 | + | ||
1155 | static inline int security_bprm_alloc(struct linux_binprm *bprm) | ||
1156 | { | ||
1157 | return 0; | ||
1158 | diff --git a/include/linux/writeback.h b/include/linux/writeback.h | ||
1159 | index c2835bb..cc0e6d9 100644 | ||
1160 | --- a/include/linux/writeback.h | ||
1161 | +++ b/include/linux/writeback.h | ||
1162 | @@ -62,7 +62,6 @@ struct writeback_control { | ||
1163 | unsigned for_writepages:1; /* This is a writepages() call */ | ||
1164 | unsigned range_cyclic:1; /* range_start is cyclic */ | ||
1165 | unsigned more_io:1; /* more io to be dispatched */ | ||
1166 | - unsigned range_cont:1; | ||
1167 | }; | ||
1168 | |||
1169 | /* | ||
1170 | diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c | ||
1171 | index f8d9680..ae51d5e 100644 | ||
1172 | --- a/kernel/time/clockevents.c | ||
1173 | +++ b/kernel/time/clockevents.c | ||
1174 | @@ -124,11 +124,12 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, | ||
1175 | */ | ||
1176 | int clockevents_register_notifier(struct notifier_block *nb) | ||
1177 | { | ||
1178 | + unsigned long flags; | ||
1179 | int ret; | ||
1180 | |||
1181 | - spin_lock(&clockevents_lock); | ||
1182 | + spin_lock_irqsave(&clockevents_lock, flags); | ||
1183 | ret = raw_notifier_chain_register(&clockevents_chain, nb); | ||
1184 | - spin_unlock(&clockevents_lock); | ||
1185 | + spin_unlock_irqrestore(&clockevents_lock, flags); | ||
1186 | |||
1187 | return ret; | ||
1188 | } | ||
1189 | @@ -165,6 +166,8 @@ static void clockevents_notify_released(void) | ||
1190 | */ | ||
1191 | void clockevents_register_device(struct clock_event_device *dev) | ||
1192 | { | ||
1193 | + unsigned long flags; | ||
1194 | + | ||
1195 | BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); | ||
1196 | /* | ||
1197 | * A nsec2cyc multiplicator of 0 is invalid and we'd crash | ||
1198 | @@ -175,13 +178,13 @@ void clockevents_register_device(struct clock_event_device *dev) | ||
1199 | WARN_ON(1); | ||
1200 | } | ||
1201 | |||
1202 | - spin_lock(&clockevents_lock); | ||
1203 | + spin_lock_irqsave(&clockevents_lock, flags); | ||
1204 | |||
1205 | list_add(&dev->list, &clockevent_devices); | ||
1206 | clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev); | ||
1207 | clockevents_notify_released(); | ||
1208 | |||
1209 | - spin_unlock(&clockevents_lock); | ||
1210 | + spin_unlock_irqrestore(&clockevents_lock, flags); | ||
1211 | } | ||
1212 | |||
1213 | /* | ||
1214 | @@ -228,8 +231,9 @@ void clockevents_exchange_device(struct clock_event_device *old, | ||
1215 | void clockevents_notify(unsigned long reason, void *arg) | ||
1216 | { | ||
1217 | struct list_head *node, *tmp; | ||
1218 | + unsigned long flags; | ||
1219 | |||
1220 | - spin_lock(&clockevents_lock); | ||
1221 | + spin_lock_irqsave(&clockevents_lock, flags); | ||
1222 | clockevents_do_notify(reason, arg); | ||
1223 | |||
1224 | switch (reason) { | ||
1225 | @@ -244,7 +248,7 @@ void clockevents_notify(unsigned long reason, void *arg) | ||
1226 | default: | ||
1227 | break; | ||
1228 | } | ||
1229 | - spin_unlock(&clockevents_lock); | ||
1230 | + spin_unlock_irqrestore(&clockevents_lock, flags); | ||
1231 | } | ||
1232 | EXPORT_SYMBOL_GPL(clockevents_notify); | ||
1233 | #endif | ||
1234 | diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c | ||
1235 | index cb01cd8..d1b3216 100644 | ||
1236 | --- a/kernel/time/tick-broadcast.c | ||
1237 | +++ b/kernel/time/tick-broadcast.c | ||
1238 | @@ -205,11 +205,11 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) | ||
1239 | * Powerstate information: The system enters/leaves a state, where | ||
1240 | * affected devices might stop | ||
1241 | */ | ||
1242 | -static void tick_do_broadcast_on_off(void *why) | ||
1243 | +static void tick_do_broadcast_on_off(unsigned long *reason) | ||
1244 | { | ||
1245 | struct clock_event_device *bc, *dev; | ||
1246 | struct tick_device *td; | ||
1247 | - unsigned long flags, *reason = why; | ||
1248 | + unsigned long flags; | ||
1249 | int cpu, bc_stopped; | ||
1250 | |||
1251 | spin_lock_irqsave(&tick_broadcast_lock, flags); | ||
1252 | @@ -276,8 +276,7 @@ void tick_broadcast_on_off(unsigned long reason, int *oncpu) | ||
1253 | printk(KERN_ERR "tick-broadcast: ignoring broadcast for " | ||
1254 | "offline CPU #%d\n", *oncpu); | ||
1255 | else | ||
1256 | - smp_call_function_single(*oncpu, tick_do_broadcast_on_off, | ||
1257 | - &reason, 1); | ||
1258 | + tick_do_broadcast_on_off(&reason); | ||
1259 | } | ||
1260 | |||
1261 | /* | ||
1262 | diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c | ||
1263 | index 8f3fb3d..dfe3995 100644 | ||
1264 | --- a/kernel/trace/trace.c | ||
1265 | +++ b/kernel/trace/trace.c | ||
1266 | @@ -3018,7 +3018,6 @@ static int trace_free_page(void) | ||
1267 | ClearPageLRU(page); | ||
1268 | list_del(&page->lru); | ||
1269 | tracing_pages_allocated--; | ||
1270 | - tracing_pages_allocated--; | ||
1271 | __free_page(page); | ||
1272 | |||
1273 | tracing_reset(data); | ||
1274 | @@ -3036,6 +3035,7 @@ static int trace_free_page(void) | ||
1275 | page = list_entry(p, struct page, lru); | ||
1276 | ClearPageLRU(page); | ||
1277 | list_del(&page->lru); | ||
1278 | + tracing_pages_allocated--; | ||
1279 | __free_page(page); | ||
1280 | |||
1281 | tracing_reset(data); | ||
1282 | diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c | ||
1283 | index 4a8ba4b..a866389 100644 | ||
1284 | --- a/lib/percpu_counter.c | ||
1285 | +++ b/lib/percpu_counter.c | ||
1286 | @@ -52,7 +52,7 @@ EXPORT_SYMBOL(__percpu_counter_add); | ||
1287 | * Add up all the per-cpu counts, return the result. This is a more accurate | ||
1288 | * but much slower version of percpu_counter_read_positive() | ||
1289 | */ | ||
1290 | -s64 __percpu_counter_sum(struct percpu_counter *fbc, int set) | ||
1291 | +s64 __percpu_counter_sum(struct percpu_counter *fbc) | ||
1292 | { | ||
1293 | s64 ret; | ||
1294 | int cpu; | ||
1295 | @@ -62,11 +62,9 @@ s64 __percpu_counter_sum(struct percpu_counter *fbc, int set) | ||
1296 | for_each_online_cpu(cpu) { | ||
1297 | s32 *pcount = per_cpu_ptr(fbc->counters, cpu); | ||
1298 | ret += *pcount; | ||
1299 | - if (set) | ||
1300 | - *pcount = 0; | ||
1301 | + *pcount = 0; | ||
1302 | } | ||
1303 | - if (set) | ||
1304 | - fbc->count = ret; | ||
1305 | + fbc->count = ret; | ||
1306 | |||
1307 | spin_unlock(&fbc->lock); | ||
1308 | return ret; | ||
1309 | diff --git a/mm/mmap.c b/mm/mmap.c | ||
1310 | index 8b5aa8e..f3e5bfe 100644 | ||
1311 | --- a/mm/mmap.c | ||
1312 | +++ b/mm/mmap.c | ||
1313 | @@ -178,7 +178,8 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | ||
1314 | |||
1315 | /* Don't let a single process grow too big: | ||
1316 | leave 3% of the size of this process for other processes */ | ||
1317 | - allowed -= mm->total_vm / 32; | ||
1318 | + if (mm) | ||
1319 | + allowed -= mm->total_vm / 32; | ||
1320 | |||
1321 | /* | ||
1322 | * cast `allowed' as a signed long because vm_committed_space | ||
1323 | diff --git a/mm/nommu.c b/mm/nommu.c | ||
1324 | index 4bf7686..7122331 100644 | ||
1325 | --- a/mm/nommu.c | ||
1326 | +++ b/mm/nommu.c | ||
1327 | @@ -1432,7 +1432,8 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | ||
1328 | |||
1329 | /* Don't let a single process grow too big: | ||
1330 | leave 3% of the size of this process for other processes */ | ||
1331 | - allowed -= current->mm->total_vm / 32; | ||
1332 | + if (mm) | ||
1333 | + allowed -= mm->total_vm / 32; | ||
1334 | |||
1335 | /* | ||
1336 | * cast `allowed' as a signed long because vm_committed_space | ||
1337 | diff --git a/mm/page-writeback.c b/mm/page-writeback.c | ||
1338 | index 5f7cdc2..e5c4ca2 100644 | ||
1339 | --- a/mm/page-writeback.c | ||
1340 | +++ b/mm/page-writeback.c | ||
1341 | @@ -1027,8 +1027,6 @@ continue_unlock: | ||
1342 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) | ||
1343 | mapping->writeback_index = done_index; | ||
1344 | |||
1345 | - if (wbc->range_cont) | ||
1346 | - wbc->range_start = index << PAGE_CACHE_SHIFT; | ||
1347 | return ret; | ||
1348 | } | ||
1349 | EXPORT_SYMBOL(write_cache_pages); | ||
1350 | diff --git a/mm/shmem.c b/mm/shmem.c | ||
1351 | index 04fb4f1..c088da1 100644 | ||
1352 | --- a/mm/shmem.c | ||
1353 | +++ b/mm/shmem.c | ||
1354 | @@ -163,8 +163,8 @@ static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb) | ||
1355 | */ | ||
1356 | static inline int shmem_acct_size(unsigned long flags, loff_t size) | ||
1357 | { | ||
1358 | - return (flags & VM_ACCOUNT)? | ||
1359 | - security_vm_enough_memory(VM_ACCT(size)): 0; | ||
1360 | + return (flags & VM_ACCOUNT) ? | ||
1361 | + security_vm_enough_memory_kern(VM_ACCT(size)) : 0; | ||
1362 | } | ||
1363 | |||
1364 | static inline void shmem_unacct_size(unsigned long flags, loff_t size) | ||
1365 | @@ -181,8 +181,8 @@ static inline void shmem_unacct_size(unsigned long flags, loff_t size) | ||
1366 | */ | ||
1367 | static inline int shmem_acct_block(unsigned long flags) | ||
1368 | { | ||
1369 | - return (flags & VM_ACCOUNT)? | ||
1370 | - 0: security_vm_enough_memory(VM_ACCT(PAGE_CACHE_SIZE)); | ||
1371 | + return (flags & VM_ACCOUNT) ? | ||
1372 | + 0 : security_vm_enough_memory_kern(VM_ACCT(PAGE_CACHE_SIZE)); | ||
1373 | } | ||
1374 | |||
1375 | static inline void shmem_unacct_blocks(unsigned long flags, long pages) | ||
1376 | diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c | ||
1377 | index e46c825..4c772de 100644 | ||
1378 | --- a/net/sunrpc/svc_xprt.c | ||
1379 | +++ b/net/sunrpc/svc_xprt.c | ||
1380 | @@ -810,6 +810,11 @@ static void svc_age_temp_xprts(unsigned long closure) | ||
1381 | void svc_delete_xprt(struct svc_xprt *xprt) | ||
1382 | { | ||
1383 | struct svc_serv *serv = xprt->xpt_server; | ||
1384 | + struct svc_deferred_req *dr; | ||
1385 | + | ||
1386 | + /* Only do this once */ | ||
1387 | + if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) | ||
1388 | + return; | ||
1389 | |||
1390 | dprintk("svc: svc_delete_xprt(%p)\n", xprt); | ||
1391 | xprt->xpt_ops->xpo_detach(xprt); | ||
1392 | @@ -824,12 +829,16 @@ void svc_delete_xprt(struct svc_xprt *xprt) | ||
1393 | * while still attached to a queue, the queue itself | ||
1394 | * is about to be destroyed (in svc_destroy). | ||
1395 | */ | ||
1396 | - if (!test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) { | ||
1397 | - BUG_ON(atomic_read(&xprt->xpt_ref.refcount) < 2); | ||
1398 | - if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | ||
1399 | - serv->sv_tmpcnt--; | ||
1400 | + if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | ||
1401 | + serv->sv_tmpcnt--; | ||
1402 | + | ||
1403 | + for (dr = svc_deferred_dequeue(xprt); dr; | ||
1404 | + dr = svc_deferred_dequeue(xprt)) { | ||
1405 | svc_xprt_put(xprt); | ||
1406 | + kfree(dr); | ||
1407 | } | ||
1408 | + | ||
1409 | + svc_xprt_put(xprt); | ||
1410 | spin_unlock_bh(&serv->sv_lock); | ||
1411 | } | ||
1412 | |||
1413 | @@ -875,17 +884,19 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many) | ||
1414 | container_of(dreq, struct svc_deferred_req, handle); | ||
1415 | struct svc_xprt *xprt = dr->xprt; | ||
1416 | |||
1417 | - if (too_many) { | ||
1418 | + spin_lock(&xprt->xpt_lock); | ||
1419 | + set_bit(XPT_DEFERRED, &xprt->xpt_flags); | ||
1420 | + if (too_many || test_bit(XPT_DEAD, &xprt->xpt_flags)) { | ||
1421 | + spin_unlock(&xprt->xpt_lock); | ||
1422 | + dprintk("revisit canceled\n"); | ||
1423 | svc_xprt_put(xprt); | ||
1424 | kfree(dr); | ||
1425 | return; | ||
1426 | } | ||
1427 | dprintk("revisit queued\n"); | ||
1428 | dr->xprt = NULL; | ||
1429 | - spin_lock(&xprt->xpt_lock); | ||
1430 | list_add(&dr->handle.recent, &xprt->xpt_deferred); | ||
1431 | spin_unlock(&xprt->xpt_lock); | ||
1432 | - set_bit(XPT_DEFERRED, &xprt->xpt_flags); | ||
1433 | svc_xprt_enqueue(xprt); | ||
1434 | svc_xprt_put(xprt); | ||
1435 | } | ||
1436 | diff --git a/security/security.c b/security/security.c | ||
1437 | index 27a315d..50b61ae 100644 | ||
1438 | --- a/security/security.c | ||
1439 | +++ b/security/security.c | ||
1440 | @@ -195,14 +195,23 @@ int security_settime(struct timespec *ts, struct timezone *tz) | ||
1441 | |||
1442 | int security_vm_enough_memory(long pages) | ||
1443 | { | ||
1444 | + WARN_ON(current->mm == NULL); | ||
1445 | return security_ops->vm_enough_memory(current->mm, pages); | ||
1446 | } | ||
1447 | |||
1448 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) | ||
1449 | { | ||
1450 | + WARN_ON(mm == NULL); | ||
1451 | return security_ops->vm_enough_memory(mm, pages); | ||
1452 | } | ||
1453 | |||
1454 | +int security_vm_enough_memory_kern(long pages) | ||
1455 | +{ | ||
1456 | + /* If current->mm is a kernel thread then we will pass NULL, | ||
1457 | + for this specific case that is fine */ | ||
1458 | + return security_ops->vm_enough_memory(current->mm, pages); | ||
1459 | +} | ||
1460 | + | ||
1461 | int security_bprm_alloc(struct linux_binprm *bprm) | ||
1462 | { | ||
1463 | return security_ops->bprm_alloc_security(bprm); | ||
1464 | diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c | ||
1465 | index 7e83131..62ebff5 100644 | ||
1466 | --- a/sound/pci/mixart/mixart.c | ||
1467 | +++ b/sound/pci/mixart/mixart.c | ||
1468 | @@ -1160,13 +1160,15 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private | ||
1469 | unsigned long count, unsigned long pos) | ||
1470 | { | ||
1471 | struct mixart_mgr *mgr = entry->private_data; | ||
1472 | + unsigned long maxsize; | ||
1473 | |||
1474 | - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ | ||
1475 | - if(count <= 0) | ||
1476 | + if (pos >= MIXART_BA0_SIZE) | ||
1477 | return 0; | ||
1478 | - if(pos + count > MIXART_BA0_SIZE) | ||
1479 | - count = (long)(MIXART_BA0_SIZE - pos); | ||
1480 | - if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count)) | ||
1481 | + maxsize = MIXART_BA0_SIZE - pos; | ||
1482 | + if (count > maxsize) | ||
1483 | + count = maxsize; | ||
1484 | + count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ | ||
1485 | + if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) | ||
1486 | return -EFAULT; | ||
1487 | return count; | ||
1488 | } | ||
1489 | @@ -1179,13 +1181,15 @@ static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private | ||
1490 | unsigned long count, unsigned long pos) | ||
1491 | { | ||
1492 | struct mixart_mgr *mgr = entry->private_data; | ||
1493 | + unsigned long maxsize; | ||
1494 | |||
1495 | - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ | ||
1496 | - if(count <= 0) | ||
1497 | + if (pos > MIXART_BA1_SIZE) | ||
1498 | return 0; | ||
1499 | - if(pos + count > MIXART_BA1_SIZE) | ||
1500 | - count = (long)(MIXART_BA1_SIZE - pos); | ||
1501 | - if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count)) | ||
1502 | + maxsize = MIXART_BA1_SIZE - pos; | ||
1503 | + if (count > maxsize) | ||
1504 | + count = maxsize; | ||
1505 | + count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ | ||
1506 | + if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) | ||
1507 | return -EFAULT; | ||
1508 | return count; | ||
1509 | } |