/[linux-patches]/genpatches-2.6/tags/3.0-30/1007_linux-3.0.8.patch
Gentoo

Contents of /genpatches-2.6/tags/3.0-30/1007_linux-3.0.8.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2206 - (show annotations) (download)
Mon Sep 17 18:58:14 2012 UTC (22 months, 1 week ago) by mpagano
File size: 44633 byte(s)
3.0-30 release
1 diff --git a/Makefile b/Makefile
2 index 11c4249..9f6e3cd 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -1,6 +1,6 @@
6 VERSION = 3
7 PATCHLEVEL = 0
8 -SUBLEVEL = 7
9 +SUBLEVEL = 8
10 EXTRAVERSION =
11 NAME = Sneaky Weasel
12
13 diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
14 index 4960686..4372763 100644
15 --- a/arch/arm/kernel/perf_event_v7.c
16 +++ b/arch/arm/kernel/perf_event_v7.c
17 @@ -264,8 +264,8 @@ static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
18 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
19 [PERF_COUNT_HW_INSTRUCTIONS] =
20 ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
21 - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_COHERENT_LINE_HIT,
22 - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_COHERENT_LINE_MISS,
23 + [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_DCACHE_ACCESS,
24 + [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_DCACHE_REFILL,
25 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
26 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
27 [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
28 diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
29 index c19571c..4a4eba5 100644
30 --- a/arch/arm/mm/init.c
31 +++ b/arch/arm/mm/init.c
32 @@ -473,6 +473,13 @@ static void __init free_unused_memmap(struct meminfo *mi)
33 */
34 bank_start = min(bank_start,
35 ALIGN(prev_bank_end, PAGES_PER_SECTION));
36 +#else
37 + /*
38 + * Align down here since the VM subsystem insists that the
39 + * memmap entries are valid from the bank start aligned to
40 + * MAX_ORDER_NR_PAGES.
41 + */
42 + bank_start = round_down(bank_start, MAX_ORDER_NR_PAGES);
43 #endif
44 /*
45 * If we had a previous bank, and there is a space
46 diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
47 index 3032644..87488b9 100644
48 --- a/arch/x86/mm/init.c
49 +++ b/arch/x86/mm/init.c
50 @@ -63,9 +63,8 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
51 #ifdef CONFIG_X86_32
52 /* for fixmap */
53 tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
54 -
55 - good_end = max_pfn_mapped << PAGE_SHIFT;
56 #endif
57 + good_end = max_pfn_mapped << PAGE_SHIFT;
58
59 base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE);
60 if (base == MEMBLOCK_ERROR)
61 diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c
62 index be44256..7835b8f 100644
63 --- a/crypto/ghash-generic.c
64 +++ b/crypto/ghash-generic.c
65 @@ -67,6 +67,9 @@ static int ghash_update(struct shash_desc *desc,
66 struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
67 u8 *dst = dctx->buffer;
68
69 + if (!ctx->gf128)
70 + return -ENOKEY;
71 +
72 if (dctx->bytes) {
73 int n = min(srclen, dctx->bytes);
74 u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
75 @@ -119,6 +122,9 @@ static int ghash_final(struct shash_desc *desc, u8 *dst)
76 struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
77 u8 *buf = dctx->buffer;
78
79 + if (!ctx->gf128)
80 + return -ENOKEY;
81 +
82 ghash_flush(ctx, dctx);
83 memcpy(dst, buf, GHASH_BLOCK_SIZE);
84
85 diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
86 index 41841a3..17cef86 100644
87 --- a/drivers/firewire/sbp2.c
88 +++ b/drivers/firewire/sbp2.c
89 @@ -1198,6 +1198,10 @@ static int sbp2_remove(struct device *dev)
90 {
91 struct fw_unit *unit = fw_unit(dev);
92 struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
93 + struct sbp2_logical_unit *lu;
94 +
95 + list_for_each_entry(lu, &tgt->lu_list, link)
96 + cancel_delayed_work_sync(&lu->work);
97
98 sbp2_target_put(tgt);
99 return 0;
100 diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
101 index ebdb0fd..9a0aee2 100644
102 --- a/drivers/gpu/drm/radeon/atom.c
103 +++ b/drivers/gpu/drm/radeon/atom.c
104 @@ -277,7 +277,12 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
105 case ATOM_ARG_FB:
106 idx = U8(*ptr);
107 (*ptr)++;
108 - val = gctx->scratch[((gctx->fb_base + idx) / 4)];
109 + if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
110 + DRM_ERROR("ATOM: fb read beyond scratch region: %d vs. %d\n",
111 + gctx->fb_base + (idx * 4), gctx->scratch_size_bytes);
112 + val = 0;
113 + } else
114 + val = gctx->scratch[(gctx->fb_base / 4) + idx];
115 if (print)
116 DEBUG("FB[0x%02X]", idx);
117 break;
118 @@ -531,7 +536,11 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
119 case ATOM_ARG_FB:
120 idx = U8(*ptr);
121 (*ptr)++;
122 - gctx->scratch[((gctx->fb_base + idx) / 4)] = val;
123 + if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
124 + DRM_ERROR("ATOM: fb write beyond scratch region: %d vs. %d\n",
125 + gctx->fb_base + (idx * 4), gctx->scratch_size_bytes);
126 + } else
127 + gctx->scratch[(gctx->fb_base / 4) + idx] = val;
128 DEBUG("FB[0x%02X]", idx);
129 break;
130 case ATOM_ARG_PLL:
131 @@ -1367,11 +1376,13 @@ int atom_allocate_fb_scratch(struct atom_context *ctx)
132
133 usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
134 }
135 + ctx->scratch_size_bytes = 0;
136 if (usage_bytes == 0)
137 usage_bytes = 20 * 1024;
138 /* allocate some scratch memory */
139 ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
140 if (!ctx->scratch)
141 return -ENOMEM;
142 + ctx->scratch_size_bytes = usage_bytes;
143 return 0;
144 }
145 diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h
146 index a589a55..93cfe20 100644
147 --- a/drivers/gpu/drm/radeon/atom.h
148 +++ b/drivers/gpu/drm/radeon/atom.h
149 @@ -137,6 +137,7 @@ struct atom_context {
150 int cs_equal, cs_above;
151 int io_mode;
152 uint32_t *scratch;
153 + int scratch_size_bytes;
154 };
155
156 extern int atom_debug;
157 diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
158 index b7f0726..e2b2d78 100644
159 --- a/drivers/gpu/drm/ttm/ttm_bo.c
160 +++ b/drivers/gpu/drm/ttm/ttm_bo.c
161 @@ -392,10 +392,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
162 * Create and bind a ttm if required.
163 */
164
165 - if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) {
166 - ret = ttm_bo_add_ttm(bo, false);
167 - if (ret)
168 - goto out_err;
169 + if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
170 + if (bo->ttm == NULL) {
171 + ret = ttm_bo_add_ttm(bo, false);
172 + if (ret)
173 + goto out_err;
174 + }
175
176 ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
177 if (ret)
178 diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
179 index 77dbf40..ae3c6f5 100644
180 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
181 +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
182 @@ -635,13 +635,13 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
183 if (ret)
184 return ret;
185
186 - ttm_bo_free_old_node(bo);
187 if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
188 (bo->ttm != NULL)) {
189 ttm_tt_unbind(bo->ttm);
190 ttm_tt_destroy(bo->ttm);
191 bo->ttm = NULL;
192 }
193 + ttm_bo_free_old_node(bo);
194 } else {
195 /**
196 * This should help pipeline ordinary buffer moves.
197 diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
198 index a756ee6..c946d90 100644
199 --- a/drivers/hid/hid-ids.h
200 +++ b/drivers/hid/hid-ids.h
201 @@ -568,6 +568,9 @@
202 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
203 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600
204
205 +#define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f
206 +#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002
207 +
208 #define USB_VENDOR_ID_SKYCABLE 0x1223
209 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
210
211 diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
212 index 0ec91c1..56d0539 100644
213 --- a/drivers/hid/hid-magicmouse.c
214 +++ b/drivers/hid/hid-magicmouse.c
215 @@ -501,9 +501,17 @@ static int magicmouse_probe(struct hid_device *hdev,
216 }
217 report->size = 6;
218
219 + /*
220 + * Some devices repond with 'invalid report id' when feature
221 + * report switching it into multitouch mode is sent to it.
222 + *
223 + * This results in -EIO from the _raw low-level transport callback,
224 + * but there seems to be no other way of switching the mode.
225 + * Thus the super-ugly hacky success check below.
226 + */
227 ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
228 HID_FEATURE_REPORT);
229 - if (ret != sizeof(feature)) {
230 + if (ret != -EIO && ret != sizeof(feature)) {
231 hid_err(hdev, "unable to request touch data (%d)\n", ret);
232 goto err_stop_hw;
233 }
234 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
235 index 621959d..4bdb5d4 100644
236 --- a/drivers/hid/usbhid/hid-quirks.c
237 +++ b/drivers/hid/usbhid/hid-quirks.c
238 @@ -89,6 +89,7 @@ static const struct hid_blacklist {
239
240 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT },
241 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT },
242 + { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
243 { 0, 0 }
244 };
245
246 diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
247 index f2b377c..36d7f27 100644
248 --- a/drivers/hwmon/w83627ehf.c
249 +++ b/drivers/hwmon/w83627ehf.c
250 @@ -390,7 +390,7 @@ temp_from_reg(u16 reg, s16 regval)
251 {
252 if (is_word_sized(reg))
253 return LM75_TEMP_FROM_REG(regval);
254 - return regval * 1000;
255 + return ((s8)regval) * 1000;
256 }
257
258 static inline u16
259 @@ -398,7 +398,8 @@ temp_to_reg(u16 reg, long temp)
260 {
261 if (is_word_sized(reg))
262 return LM75_TEMP_TO_REG(temp);
263 - return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000), 1000);
264 + return (s8)DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000),
265 + 1000);
266 }
267
268 /* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
269 @@ -1715,7 +1716,8 @@ static void w83627ehf_device_remove_files(struct device *dev)
270 }
271
272 /* Get the monitoring functions started */
273 -static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
274 +static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data,
275 + enum kinds kind)
276 {
277 int i;
278 u8 tmp, diode;
279 @@ -1746,10 +1748,16 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
280 w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01);
281
282 /* Get thermal sensor types */
283 - diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
284 + switch (kind) {
285 + case w83627ehf:
286 + diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
287 + break;
288 + default:
289 + diode = 0x70;
290 + }
291 for (i = 0; i < 3; i++) {
292 if ((tmp & (0x02 << i)))
293 - data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 2;
294 + data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3;
295 else
296 data->temp_type[i] = 4; /* thermistor */
297 }
298 @@ -2016,7 +2024,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
299 }
300
301 /* Initialize the chip */
302 - w83627ehf_init_device(data);
303 + w83627ehf_init_device(data, sio_data->kind);
304
305 data->vrm = vid_which_vrm();
306 superio_enter(sio_data->sioreg);
307 diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c
308 index 48fea37..29e2399 100644
309 --- a/drivers/media/video/uvc/uvc_entity.c
310 +++ b/drivers/media/video/uvc/uvc_entity.c
311 @@ -49,7 +49,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
312 if (remote == NULL)
313 return -EINVAL;
314
315 - source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING)
316 + source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
317 ? (remote->vdev ? &remote->vdev->entity : NULL)
318 : &remote->subdev.entity;
319 if (source == NULL)
320 diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
321 index d347116..1658575 100644
322 --- a/drivers/platform/x86/samsung-laptop.c
323 +++ b/drivers/platform/x86/samsung-laptop.c
324 @@ -601,6 +601,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
325 .callback = dmi_check_cb,
326 },
327 {
328 + .ident = "N150/N210/N220",
329 + .matches = {
330 + DMI_MATCH(DMI_SYS_VENDOR,
331 + "SAMSUNG ELECTRONICS CO., LTD."),
332 + DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
333 + DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
334 + },
335 + .callback = dmi_check_cb,
336 + },
337 + {
338 .ident = "N150/N210/N220/N230",
339 .matches = {
340 DMI_MATCH(DMI_SYS_VENDOR,
341 diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
342 index fc7e57b..53e7d72 100644
343 --- a/fs/cifs/cifsfs.c
344 +++ b/fs/cifs/cifsfs.c
345 @@ -566,6 +566,12 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
346 struct inode *dir = dentry->d_inode;
347 struct dentry *child;
348
349 + if (!dir) {
350 + dput(dentry);
351 + dentry = ERR_PTR(-ENOENT);
352 + break;
353 + }
354 +
355 /* skip separators */
356 while (*s == sep)
357 s++;
358 @@ -581,10 +587,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
359 mutex_unlock(&dir->i_mutex);
360 dput(dentry);
361 dentry = child;
362 - if (!dentry->d_inode) {
363 - dput(dentry);
364 - dentry = ERR_PTR(-ENOENT);
365 - }
366 } while (!IS_ERR(dentry));
367 _FreeXid(xid);
368 kfree(full_path);
369 diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
370 index 168a80f..5cb8614 100644
371 --- a/fs/fuse/dev.c
372 +++ b/fs/fuse/dev.c
373 @@ -258,10 +258,14 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
374 forget->forget_one.nlookup = nlookup;
375
376 spin_lock(&fc->lock);
377 - fc->forget_list_tail->next = forget;
378 - fc->forget_list_tail = forget;
379 - wake_up(&fc->waitq);
380 - kill_fasync(&fc->fasync, SIGIO, POLL_IN);
381 + if (fc->connected) {
382 + fc->forget_list_tail->next = forget;
383 + fc->forget_list_tail = forget;
384 + wake_up(&fc->waitq);
385 + kill_fasync(&fc->fasync, SIGIO, POLL_IN);
386 + } else {
387 + kfree(forget);
388 + }
389 spin_unlock(&fc->lock);
390 }
391
392 diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
393 index d685752..4e7f64b 100644
394 --- a/fs/hfsplus/hfsplus_fs.h
395 +++ b/fs/hfsplus/hfsplus_fs.h
396 @@ -13,6 +13,7 @@
397 #include <linux/fs.h>
398 #include <linux/mutex.h>
399 #include <linux/buffer_head.h>
400 +#include <linux/blkdev.h>
401 #include "hfsplus_raw.h"
402
403 #define DBG_BNODE_REFS 0x00000001
404 @@ -110,7 +111,9 @@ struct hfsplus_vh;
405 struct hfs_btree;
406
407 struct hfsplus_sb_info {
408 + void *s_vhdr_buf;
409 struct hfsplus_vh *s_vhdr;
410 + void *s_backup_vhdr_buf;
411 struct hfsplus_vh *s_backup_vhdr;
412 struct hfs_btree *ext_tree;
413 struct hfs_btree *cat_tree;
414 @@ -258,6 +261,15 @@ struct hfsplus_readdir_data {
415 struct hfsplus_cat_key key;
416 };
417
418 +/*
419 + * Find minimum acceptible I/O size for an hfsplus sb.
420 + */
421 +static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
422 +{
423 + return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev),
424 + HFSPLUS_SECTOR_SIZE);
425 +}
426 +
427 #define hfs_btree_open hfsplus_btree_open
428 #define hfs_btree_close hfsplus_btree_close
429 #define hfs_btree_write hfsplus_btree_write
430 @@ -436,8 +448,8 @@ int hfsplus_compare_dentry(const struct dentry *parent,
431 /* wrapper.c */
432 int hfsplus_read_wrapper(struct super_block *);
433 int hfs_part_find(struct super_block *, sector_t *, sector_t *);
434 -int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
435 - void *data, int rw);
436 +int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
437 + void *buf, void **data, int rw);
438
439 /* time macros */
440 #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U)
441 diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
442 index 40ad88c..eb355d8 100644
443 --- a/fs/hfsplus/part_tbl.c
444 +++ b/fs/hfsplus/part_tbl.c
445 @@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
446 return -ENOENT;
447 }
448
449 -static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
450 - sector_t *part_start, sector_t *part_size)
451 +static int hfs_parse_new_pmap(struct super_block *sb, void *buf,
452 + struct new_pmap *pm, sector_t *part_start, sector_t *part_size)
453 {
454 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
455 int size = be32_to_cpu(pm->pmMapBlkCnt);
456 + int buf_size = hfsplus_min_io_size(sb);
457 int res;
458 int i = 0;
459
460 @@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
461 if (++i >= size)
462 return -ENOENT;
463
464 - res = hfsplus_submit_bio(sb->s_bdev,
465 - *part_start + HFS_PMAP_BLK + i,
466 - pm, READ);
467 - if (res)
468 - return res;
469 + pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE);
470 + if ((u8 *)pm - (u8 *)buf >= buf_size) {
471 + res = hfsplus_submit_bio(sb,
472 + *part_start + HFS_PMAP_BLK + i,
473 + buf, (void **)&pm, READ);
474 + if (res)
475 + return res;
476 + }
477 } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
478
479 return -ENOENT;
480 @@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
481 int hfs_part_find(struct super_block *sb,
482 sector_t *part_start, sector_t *part_size)
483 {
484 - void *data;
485 + void *buf, *data;
486 int res;
487
488 - data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
489 - if (!data)
490 + buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
491 + if (!buf)
492 return -ENOMEM;
493
494 - res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK,
495 - data, READ);
496 + res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK,
497 + buf, &data, READ);
498 if (res)
499 goto out;
500
501 @@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb,
502 res = hfs_parse_old_pmap(sb, data, part_start, part_size);
503 break;
504 case HFS_NEW_PMAP_MAGIC:
505 - res = hfs_parse_new_pmap(sb, data, part_start, part_size);
506 + res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size);
507 break;
508 default:
509 res = -ENOENT;
510 break;
511 }
512 out:
513 - kfree(data);
514 + kfree(buf);
515 return res;
516 }
517 diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
518 index 84a47b7..c3a76fd 100644
519 --- a/fs/hfsplus/super.c
520 +++ b/fs/hfsplus/super.c
521 @@ -197,17 +197,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
522 write_backup = 1;
523 }
524
525 - error2 = hfsplus_submit_bio(sb->s_bdev,
526 + error2 = hfsplus_submit_bio(sb,
527 sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
528 - sbi->s_vhdr, WRITE_SYNC);
529 + sbi->s_vhdr_buf, NULL, WRITE_SYNC);
530 if (!error)
531 error = error2;
532 if (!write_backup)
533 goto out;
534
535 - error2 = hfsplus_submit_bio(sb->s_bdev,
536 + error2 = hfsplus_submit_bio(sb,
537 sbi->part_start + sbi->sect_count - 2,
538 - sbi->s_backup_vhdr, WRITE_SYNC);
539 + sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC);
540 if (!error)
541 error2 = error;
542 out:
543 @@ -251,8 +251,8 @@ static void hfsplus_put_super(struct super_block *sb)
544 hfs_btree_close(sbi->ext_tree);
545 iput(sbi->alloc_file);
546 iput(sbi->hidden_dir);
547 - kfree(sbi->s_vhdr);
548 - kfree(sbi->s_backup_vhdr);
549 + kfree(sbi->s_vhdr_buf);
550 + kfree(sbi->s_backup_vhdr_buf);
551 unload_nls(sbi->nls);
552 kfree(sb->s_fs_info);
553 sb->s_fs_info = NULL;
554 @@ -508,8 +508,8 @@ out_close_cat_tree:
555 out_close_ext_tree:
556 hfs_btree_close(sbi->ext_tree);
557 out_free_vhdr:
558 - kfree(sbi->s_vhdr);
559 - kfree(sbi->s_backup_vhdr);
560 + kfree(sbi->s_vhdr_buf);
561 + kfree(sbi->s_backup_vhdr_buf);
562 out_unload_nls:
563 unload_nls(sbi->nls);
564 unload_nls(nls);
565 diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
566 index 4ac88ff..7b8112d 100644
567 --- a/fs/hfsplus/wrapper.c
568 +++ b/fs/hfsplus/wrapper.c
569 @@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err)
570 complete(bio->bi_private);
571 }
572
573 -int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
574 - void *data, int rw)
575 +/*
576 + * hfsplus_submit_bio - Perfrom block I/O
577 + * @sb: super block of volume for I/O
578 + * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes
579 + * @buf: buffer for I/O
580 + * @data: output pointer for location of requested data
581 + * @rw: direction of I/O
582 + *
583 + * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than
584 + * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads
585 + * @data will return a pointer to the start of the requested sector,
586 + * which may not be the same location as @buf.
587 + *
588 + * If @sector is not aligned to the bdev logical block size it will
589 + * be rounded down. For writes this means that @buf should contain data
590 + * that starts at the rounded-down address. As long as the data was
591 + * read using hfsplus_submit_bio() and the same buffer is used things
592 + * will work correctly.
593 + */
594 +int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
595 + void *buf, void **data, int rw)
596 {
597 DECLARE_COMPLETION_ONSTACK(wait);
598 struct bio *bio;
599 int ret = 0;
600 + unsigned int io_size;
601 + loff_t start;
602 + int offset;
603 +
604 + /*
605 + * Align sector to hardware sector size and find offset. We
606 + * assume that io_size is a power of two, which _should_
607 + * be true.
608 + */
609 + io_size = hfsplus_min_io_size(sb);
610 + start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT;
611 + offset = start & (io_size - 1);
612 + sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1);
613
614 bio = bio_alloc(GFP_NOIO, 1);
615 bio->bi_sector = sector;
616 - bio->bi_bdev = bdev;
617 + bio->bi_bdev = sb->s_bdev;
618 bio->bi_end_io = hfsplus_end_io_sync;
619 bio->bi_private = &wait;
620
621 - /*
622 - * We always submit one sector at a time, so bio_add_page must not fail.
623 - */
624 - if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE,
625 - offset_in_page(data)) != HFSPLUS_SECTOR_SIZE)
626 - BUG();
627 + if (!(rw & WRITE) && data)
628 + *data = (u8 *)buf + offset;
629 +
630 + while (io_size > 0) {
631 + unsigned int page_offset = offset_in_page(buf);
632 + unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset,
633 + io_size);
634 +
635 + ret = bio_add_page(bio, virt_to_page(buf), len, page_offset);
636 + if (ret != len) {
637 + ret = -EIO;
638 + goto out;
639 + }
640 + io_size -= len;
641 + buf = (u8 *)buf + len;
642 + }
643
644 submit_bio(rw, bio);
645 wait_for_completion(&wait);
646 @@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
647 if (!bio_flagged(bio, BIO_UPTODATE))
648 ret = -EIO;
649
650 +out:
651 bio_put(bio);
652 - return ret;
653 + return ret < 0 ? ret : 0;
654 }
655
656 static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
657 @@ -147,17 +190,17 @@ int hfsplus_read_wrapper(struct super_block *sb)
658 }
659
660 error = -ENOMEM;
661 - sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
662 - if (!sbi->s_vhdr)
663 + sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
664 + if (!sbi->s_vhdr_buf)
665 goto out;
666 - sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
667 - if (!sbi->s_backup_vhdr)
668 + sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
669 + if (!sbi->s_backup_vhdr_buf)
670 goto out_free_vhdr;
671
672 reread:
673 - error = hfsplus_submit_bio(sb->s_bdev,
674 - part_start + HFSPLUS_VOLHEAD_SECTOR,
675 - sbi->s_vhdr, READ);
676 + error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR,
677 + sbi->s_vhdr_buf, (void **)&sbi->s_vhdr,
678 + READ);
679 if (error)
680 goto out_free_backup_vhdr;
681
682 @@ -186,9 +229,9 @@ reread:
683 goto reread;
684 }
685
686 - error = hfsplus_submit_bio(sb->s_bdev,
687 - part_start + part_size - 2,
688 - sbi->s_backup_vhdr, READ);
689 + error = hfsplus_submit_bio(sb, part_start + part_size - 2,
690 + sbi->s_backup_vhdr_buf,
691 + (void **)&sbi->s_backup_vhdr, READ);
692 if (error)
693 goto out_free_backup_vhdr;
694
695 @@ -232,9 +275,9 @@ reread:
696 return 0;
697
698 out_free_backup_vhdr:
699 - kfree(sbi->s_backup_vhdr);
700 + kfree(sbi->s_backup_vhdr_buf);
701 out_free_vhdr:
702 - kfree(sbi->s_vhdr);
703 + kfree(sbi->s_vhdr_buf);
704 out:
705 return error;
706 }
707 diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
708 index 8633521..8731516 100644
709 --- a/fs/xfs/linux-2.6/xfs_linux.h
710 +++ b/fs/xfs/linux-2.6/xfs_linux.h
711 @@ -70,6 +70,8 @@
712 #include <linux/ctype.h>
713 #include <linux/writeback.h>
714 #include <linux/capability.h>
715 +#include <linux/kthread.h>
716 +#include <linux/freezer.h>
717 #include <linux/list_sort.h>
718
719 #include <asm/page.h>
720 diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
721 index a1a881e..347cae9 100644
722 --- a/fs/xfs/linux-2.6/xfs_super.c
723 +++ b/fs/xfs/linux-2.6/xfs_super.c
724 @@ -1412,37 +1412,35 @@ xfs_fs_fill_super(
725 sb->s_time_gran = 1;
726 set_posix_acl_flag(sb);
727
728 - error = xfs_syncd_init(mp);
729 - if (error)
730 - goto out_filestream_unmount;
731 -
732 xfs_inode_shrinker_register(mp);
733
734 error = xfs_mountfs(mp);
735 if (error)
736 - goto out_syncd_stop;
737 + goto out_filestream_unmount;
738 +
739 + error = xfs_syncd_init(mp);
740 + if (error)
741 + goto out_unmount;
742
743 root = igrab(VFS_I(mp->m_rootip));
744 if (!root) {
745 error = ENOENT;
746 - goto fail_unmount;
747 + goto out_syncd_stop;
748 }
749 if (is_bad_inode(root)) {
750 error = EINVAL;
751 - goto fail_vnrele;
752 + goto out_syncd_stop;
753 }
754 sb->s_root = d_alloc_root(root);
755 if (!sb->s_root) {
756 error = ENOMEM;
757 - goto fail_vnrele;
758 + goto out_iput;
759 }
760
761 return 0;
762
763 - out_syncd_stop:
764 - xfs_inode_shrinker_unregister(mp);
765 - xfs_syncd_stop(mp);
766 out_filestream_unmount:
767 + xfs_inode_shrinker_unregister(mp);
768 xfs_filestream_unmount(mp);
769 out_free_sb:
770 xfs_freesb(mp);
771 @@ -1456,17 +1454,12 @@ xfs_fs_fill_super(
772 out:
773 return -error;
774
775 - fail_vnrele:
776 - if (sb->s_root) {
777 - dput(sb->s_root);
778 - sb->s_root = NULL;
779 - } else {
780 - iput(root);
781 - }
782 -
783 - fail_unmount:
784 - xfs_inode_shrinker_unregister(mp);
785 + out_iput:
786 + iput(root);
787 + out_syncd_stop:
788 xfs_syncd_stop(mp);
789 + out_unmount:
790 + xfs_inode_shrinker_unregister(mp);
791
792 /*
793 * Blow away any referenced inode in the filestreams cache.
794 @@ -1667,24 +1660,13 @@ xfs_init_workqueues(void)
795 */
796 xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8);
797 if (!xfs_syncd_wq)
798 - goto out;
799 -
800 - xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8);
801 - if (!xfs_ail_wq)
802 - goto out_destroy_syncd;
803 -
804 + return -ENOMEM;
805 return 0;
806 -
807 -out_destroy_syncd:
808 - destroy_workqueue(xfs_syncd_wq);
809 -out:
810 - return -ENOMEM;
811 }
812
813 STATIC void
814 xfs_destroy_workqueues(void)
815 {
816 - destroy_workqueue(xfs_ail_wq);
817 destroy_workqueue(xfs_syncd_wq);
818 }
819
820 diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
821 index 9e0e2fa..8126fc2 100644
822 --- a/fs/xfs/quota/xfs_dquot_item.c
823 +++ b/fs/xfs/quota/xfs_dquot_item.c
824 @@ -183,13 +183,14 @@ xfs_qm_dqunpin_wait(
825 * search the buffer cache can be a time consuming thing, and AIL lock is a
826 * spinlock.
827 */
828 -STATIC void
829 +STATIC bool
830 xfs_qm_dquot_logitem_pushbuf(
831 struct xfs_log_item *lip)
832 {
833 struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
834 struct xfs_dquot *dqp = qlip->qli_dquot;
835 struct xfs_buf *bp;
836 + bool ret = true;
837
838 ASSERT(XFS_DQ_IS_LOCKED(dqp));
839
840 @@ -201,17 +202,20 @@ xfs_qm_dquot_logitem_pushbuf(
841 if (completion_done(&dqp->q_flush) ||
842 !(lip->li_flags & XFS_LI_IN_AIL)) {
843 xfs_dqunlock(dqp);
844 - return;
845 + return true;
846 }
847
848 bp = xfs_incore(dqp->q_mount->m_ddev_targp, qlip->qli_format.qlf_blkno,
849 dqp->q_mount->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK);
850 xfs_dqunlock(dqp);
851 if (!bp)
852 - return;
853 + return true;
854 if (XFS_BUF_ISDELAYWRITE(bp))
855 xfs_buf_delwri_promote(bp);
856 + if (XFS_BUF_ISPINNED(bp))
857 + ret = false;
858 xfs_buf_relse(bp);
859 + return ret;
860 }
861
862 /*
863 diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
864 index 7b7e005..a7342e8 100644
865 --- a/fs/xfs/xfs_buf_item.c
866 +++ b/fs/xfs/xfs_buf_item.c
867 @@ -632,7 +632,7 @@ xfs_buf_item_push(
868 * the xfsbufd to get this buffer written. We have to unlock the buffer
869 * to allow the xfsbufd to write it, too.
870 */
871 -STATIC void
872 +STATIC bool
873 xfs_buf_item_pushbuf(
874 struct xfs_log_item *lip)
875 {
876 @@ -646,6 +646,7 @@ xfs_buf_item_pushbuf(
877
878 xfs_buf_delwri_promote(bp);
879 xfs_buf_relse(bp);
880 + return true;
881 }
882
883 STATIC void
884 diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
885 index b1e88d5..391044c 100644
886 --- a/fs/xfs/xfs_inode_item.c
887 +++ b/fs/xfs/xfs_inode_item.c
888 @@ -713,13 +713,14 @@ xfs_inode_item_committed(
889 * marked delayed write. If that's the case, we'll promote it and that will
890 * allow the caller to write the buffer by triggering the xfsbufd to run.
891 */
892 -STATIC void
893 +STATIC bool
894 xfs_inode_item_pushbuf(
895 struct xfs_log_item *lip)
896 {
897 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
898 struct xfs_inode *ip = iip->ili_inode;
899 struct xfs_buf *bp;
900 + bool ret = true;
901
902 ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
903
904 @@ -730,7 +731,7 @@ xfs_inode_item_pushbuf(
905 if (completion_done(&ip->i_flush) ||
906 !(lip->li_flags & XFS_LI_IN_AIL)) {
907 xfs_iunlock(ip, XFS_ILOCK_SHARED);
908 - return;
909 + return true;
910 }
911
912 bp = xfs_incore(ip->i_mount->m_ddev_targp, iip->ili_format.ilf_blkno,
913 @@ -738,10 +739,13 @@ xfs_inode_item_pushbuf(
914
915 xfs_iunlock(ip, XFS_ILOCK_SHARED);
916 if (!bp)
917 - return;
918 + return true;
919 if (XFS_BUF_ISDELAYWRITE(bp))
920 xfs_buf_delwri_promote(bp);
921 + if (XFS_BUF_ISPINNED(bp))
922 + ret = false;
923 xfs_buf_relse(bp);
924 + return ret;
925 }
926
927 /*
928 diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
929 index c83f63b..efc147f 100644
930 --- a/fs/xfs/xfs_trans.c
931 +++ b/fs/xfs/xfs_trans.c
932 @@ -1426,6 +1426,7 @@ xfs_trans_committed(
933 static inline void
934 xfs_log_item_batch_insert(
935 struct xfs_ail *ailp,
936 + struct xfs_ail_cursor *cur,
937 struct xfs_log_item **log_items,
938 int nr_items,
939 xfs_lsn_t commit_lsn)
940 @@ -1434,7 +1435,7 @@ xfs_log_item_batch_insert(
941
942 spin_lock(&ailp->xa_lock);
943 /* xfs_trans_ail_update_bulk drops ailp->xa_lock */
944 - xfs_trans_ail_update_bulk(ailp, log_items, nr_items, commit_lsn);
945 + xfs_trans_ail_update_bulk(ailp, cur, log_items, nr_items, commit_lsn);
946
947 for (i = 0; i < nr_items; i++)
948 IOP_UNPIN(log_items[i], 0);
949 @@ -1452,6 +1453,13 @@ xfs_log_item_batch_insert(
950 * as an iclog write error even though we haven't started any IO yet. Hence in
951 * this case all we need to do is IOP_COMMITTED processing, followed by an
952 * IOP_UNPIN(aborted) call.
953 + *
954 + * The AIL cursor is used to optimise the insert process. If commit_lsn is not
955 + * at the end of the AIL, the insert cursor avoids the need to walk
956 + * the AIL to find the insertion point on every xfs_log_item_batch_insert()
957 + * call. This saves a lot of needless list walking and is a net win, even
958 + * though it slightly increases that amount of AIL lock traffic to set it up
959 + * and tear it down.
960 */
961 void
962 xfs_trans_committed_bulk(
963 @@ -1463,8 +1471,13 @@ xfs_trans_committed_bulk(
964 #define LOG_ITEM_BATCH_SIZE 32
965 struct xfs_log_item *log_items[LOG_ITEM_BATCH_SIZE];
966 struct xfs_log_vec *lv;
967 + struct xfs_ail_cursor cur;
968 int i = 0;
969
970 + spin_lock(&ailp->xa_lock);
971 + xfs_trans_ail_cursor_last(ailp, &cur, commit_lsn);
972 + spin_unlock(&ailp->xa_lock);
973 +
974 /* unpin all the log items */
975 for (lv = log_vector; lv; lv = lv->lv_next ) {
976 struct xfs_log_item *lip = lv->lv_item;
977 @@ -1493,7 +1506,9 @@ xfs_trans_committed_bulk(
978 /*
979 * Not a bulk update option due to unusual item_lsn.
980 * Push into AIL immediately, rechecking the lsn once
981 - * we have the ail lock. Then unpin the item.
982 + * we have the ail lock. Then unpin the item. This does
983 + * not affect the AIL cursor the bulk insert path is
984 + * using.
985 */
986 spin_lock(&ailp->xa_lock);
987 if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0)
988 @@ -1507,7 +1522,7 @@ xfs_trans_committed_bulk(
989 /* Item is a candidate for bulk AIL insert. */
990 log_items[i++] = lv->lv_item;
991 if (i >= LOG_ITEM_BATCH_SIZE) {
992 - xfs_log_item_batch_insert(ailp, log_items,
993 + xfs_log_item_batch_insert(ailp, &cur, log_items,
994 LOG_ITEM_BATCH_SIZE, commit_lsn);
995 i = 0;
996 }
997 @@ -1515,7 +1530,11 @@ xfs_trans_committed_bulk(
998
999 /* make sure we insert the remainder! */
1000 if (i)
1001 - xfs_log_item_batch_insert(ailp, log_items, i, commit_lsn);
1002 + xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn);
1003 +
1004 + spin_lock(&ailp->xa_lock);
1005 + xfs_trans_ail_cursor_done(ailp, &cur);
1006 + spin_unlock(&ailp->xa_lock);
1007 }
1008
1009 /*
1010 diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
1011 index 06a9759..53597f4 100644
1012 --- a/fs/xfs/xfs_trans.h
1013 +++ b/fs/xfs/xfs_trans.h
1014 @@ -350,7 +350,7 @@ typedef struct xfs_item_ops {
1015 void (*iop_unlock)(xfs_log_item_t *);
1016 xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
1017 void (*iop_push)(xfs_log_item_t *);
1018 - void (*iop_pushbuf)(xfs_log_item_t *);
1019 + bool (*iop_pushbuf)(xfs_log_item_t *);
1020 void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
1021 } xfs_item_ops_t;
1022
1023 diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
1024 index 5fc2380..a4c281b 100644
1025 --- a/fs/xfs/xfs_trans_ail.c
1026 +++ b/fs/xfs/xfs_trans_ail.c
1027 @@ -28,8 +28,6 @@
1028 #include "xfs_trans_priv.h"
1029 #include "xfs_error.h"
1030
1031 -struct workqueue_struct *xfs_ail_wq; /* AIL workqueue */
1032 -
1033 #ifdef DEBUG
1034 /*
1035 * Check that the list is sorted as it should be.
1036 @@ -272,9 +270,9 @@ xfs_trans_ail_cursor_clear(
1037 }
1038
1039 /*
1040 - * Return the item in the AIL with the current lsn.
1041 - * Return the current tree generation number for use
1042 - * in calls to xfs_trans_next_ail().
1043 + * Initialise the cursor to the first item in the AIL with the given @lsn.
1044 + * This searches the list from lowest LSN to highest. Pass a @lsn of zero
1045 + * to initialise the cursor to the first item in the AIL.
1046 */
1047 xfs_log_item_t *
1048 xfs_trans_ail_cursor_first(
1049 @@ -300,31 +298,97 @@ out:
1050 }
1051
1052 /*
1053 - * splice the log item list into the AIL at the given LSN.
1054 + * Initialise the cursor to the last item in the AIL with the given @lsn.
1055 + * This searches the list from highest LSN to lowest. If there is no item with
1056 + * the value of @lsn, then it sets the cursor to the last item with an LSN lower
1057 + * than @lsn.
1058 + */
1059 +static struct xfs_log_item *
1060 +__xfs_trans_ail_cursor_last(
1061 + struct xfs_ail *ailp,
1062 + xfs_lsn_t lsn)
1063 +{
1064 + xfs_log_item_t *lip;
1065 +
1066 + list_for_each_entry_reverse(lip, &ailp->xa_ail, li_ail) {
1067 + if (XFS_LSN_CMP(lip->li_lsn, lsn) <= 0)
1068 + return lip;
1069 + }
1070 + return NULL;
1071 +}
1072 +
1073 +/*
1074 + * Initialise the cursor to the last item in the AIL with the given @lsn.
1075 + * This searches the list from highest LSN to lowest.
1076 + */
1077 +struct xfs_log_item *
1078 +xfs_trans_ail_cursor_last(
1079 + struct xfs_ail *ailp,
1080 + struct xfs_ail_cursor *cur,
1081 + xfs_lsn_t lsn)
1082 +{
1083 + xfs_trans_ail_cursor_init(ailp, cur);
1084 + cur->item = __xfs_trans_ail_cursor_last(ailp, lsn);
1085 + return cur->item;
1086 +}
1087 +
1088 +/*
1089 + * splice the log item list into the AIL at the given LSN. We splice to the
1090 + * tail of the given LSN to maintain insert order for push traversals. The
1091 + * cursor is optional, allowing repeated updates to the same LSN to avoid
1092 + * repeated traversals.
1093 */
1094 static void
1095 xfs_ail_splice(
1096 - struct xfs_ail *ailp,
1097 - struct list_head *list,
1098 - xfs_lsn_t lsn)
1099 + struct xfs_ail *ailp,
1100 + struct xfs_ail_cursor *cur,
1101 + struct list_head *list,
1102 + xfs_lsn_t lsn)
1103 {
1104 - xfs_log_item_t *next_lip;
1105 + struct xfs_log_item *lip = cur ? cur->item : NULL;
1106 + struct xfs_log_item *next_lip;
1107
1108 - /* If the list is empty, just insert the item. */
1109 - if (list_empty(&ailp->xa_ail)) {
1110 - list_splice(list, &ailp->xa_ail);
1111 - return;
1112 - }
1113 + /*
1114 + * Get a new cursor if we don't have a placeholder or the existing one
1115 + * has been invalidated.
1116 + */
1117 + if (!lip || (__psint_t)lip & 1) {
1118 + lip = __xfs_trans_ail_cursor_last(ailp, lsn);
1119
1120 - list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
1121 - if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0)
1122 - break;
1123 + if (!lip) {
1124 + /* The list is empty, so just splice and return. */
1125 + if (cur)
1126 + cur->item = NULL;
1127 + list_splice(list, &ailp->xa_ail);
1128 + return;
1129 + }
1130 }
1131
1132 - ASSERT(&next_lip->li_ail == &ailp->xa_ail ||
1133 - XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0);
1134 -
1135 - list_splice_init(list, &next_lip->li_ail);
1136 + /*
1137 + * Our cursor points to the item we want to insert _after_, so we have
1138 + * to update the cursor to point to the end of the list we are splicing
1139 + * in so that it points to the correct location for the next splice.
1140 + * i.e. before the splice
1141 + *
1142 + * lsn -> lsn -> lsn + x -> lsn + x ...
1143 + * ^
1144 + * | cursor points here
1145 + *
1146 + * After the splice we have:
1147 + *
1148 + * lsn -> lsn -> lsn -> lsn -> .... -> lsn -> lsn + x -> lsn + x ...
1149 + * ^ ^
1150 + * | cursor points here | needs to move here
1151 + *
1152 + * So we set the cursor to the last item in the list to be spliced
1153 + * before we execute the splice, resulting in the cursor pointing to
1154 + * the correct item after the splice occurs.
1155 + */
1156 + if (cur) {
1157 + next_lip = list_entry(list->prev, struct xfs_log_item, li_ail);
1158 + cur->item = next_lip;
1159 + }
1160 + list_splice(list, &lip->li_ail);
1161 }
1162
1163 /*
1164 @@ -340,16 +404,10 @@ xfs_ail_delete(
1165 xfs_trans_ail_cursor_clear(ailp, lip);
1166 }
1167
1168 -/*
1169 - * xfs_ail_worker does the work of pushing on the AIL. It will requeue itself
1170 - * to run at a later time if there is more work to do to complete the push.
1171 - */
1172 -STATIC void
1173 -xfs_ail_worker(
1174 - struct work_struct *work)
1175 +static long
1176 +xfsaild_push(
1177 + struct xfs_ail *ailp)
1178 {
1179 - struct xfs_ail *ailp = container_of(to_delayed_work(work),
1180 - struct xfs_ail, xa_work);
1181 xfs_mount_t *mp = ailp->xa_mount;
1182 struct xfs_ail_cursor *cur = &ailp->xa_cursors;
1183 xfs_log_item_t *lip;
1184 @@ -412,8 +470,13 @@ xfs_ail_worker(
1185
1186 case XFS_ITEM_PUSHBUF:
1187 XFS_STATS_INC(xs_push_ail_pushbuf);
1188 - IOP_PUSHBUF(lip);
1189 - ailp->xa_last_pushed_lsn = lsn;
1190 +
1191 + if (!IOP_PUSHBUF(lip)) {
1192 + stuck++;
1193 + flush_log = 1;
1194 + } else {
1195 + ailp->xa_last_pushed_lsn = lsn;
1196 + }
1197 push_xfsbufd = 1;
1198 break;
1199
1200 @@ -425,7 +488,6 @@ xfs_ail_worker(
1201
1202 case XFS_ITEM_LOCKED:
1203 XFS_STATS_INC(xs_push_ail_locked);
1204 - ailp->xa_last_pushed_lsn = lsn;
1205 stuck++;
1206 break;
1207
1208 @@ -486,20 +548,6 @@ out_done:
1209 /* We're past our target or empty, so idle */
1210 ailp->xa_last_pushed_lsn = 0;
1211
1212 - /*
1213 - * We clear the XFS_AIL_PUSHING_BIT first before checking
1214 - * whether the target has changed. If the target has changed,
1215 - * this pushes the requeue race directly onto the result of the
1216 - * atomic test/set bit, so we are guaranteed that either the
1217 - * the pusher that changed the target or ourselves will requeue
1218 - * the work (but not both).
1219 - */
1220 - clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
1221 - smp_rmb();
1222 - if (XFS_LSN_CMP(ailp->xa_target, target) == 0 ||
1223 - test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
1224 - return;
1225 -
1226 tout = 50;
1227 } else if (XFS_LSN_CMP(lsn, target) >= 0) {
1228 /*
1229 @@ -522,9 +570,30 @@ out_done:
1230 tout = 20;
1231 }
1232
1233 - /* There is more to do, requeue us. */
1234 - queue_delayed_work(xfs_syncd_wq, &ailp->xa_work,
1235 - msecs_to_jiffies(tout));
1236 + return tout;
1237 +}
1238 +
1239 +static int
1240 +xfsaild(
1241 + void *data)
1242 +{
1243 + struct xfs_ail *ailp = data;
1244 + long tout = 0; /* milliseconds */
1245 +
1246 + while (!kthread_should_stop()) {
1247 + if (tout && tout <= 20)
1248 + __set_current_state(TASK_KILLABLE);
1249 + else
1250 + __set_current_state(TASK_INTERRUPTIBLE);
1251 + schedule_timeout(tout ?
1252 + msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT);
1253 +
1254 + try_to_freeze();
1255 +
1256 + tout = xfsaild_push(ailp);
1257 + }
1258 +
1259 + return 0;
1260 }
1261
1262 /*
1263 @@ -559,8 +628,9 @@ xfs_ail_push(
1264 */
1265 smp_wmb();
1266 xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn);
1267 - if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
1268 - queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0);
1269 + smp_wmb();
1270 +
1271 + wake_up_process(ailp->xa_task);
1272 }
1273
1274 /*
1275 @@ -645,6 +715,7 @@ xfs_trans_unlocked_item(
1276 void
1277 xfs_trans_ail_update_bulk(
1278 struct xfs_ail *ailp,
1279 + struct xfs_ail_cursor *cur,
1280 struct xfs_log_item **log_items,
1281 int nr_items,
1282 xfs_lsn_t lsn) __releases(ailp->xa_lock)
1283 @@ -674,7 +745,7 @@ xfs_trans_ail_update_bulk(
1284 list_add(&lip->li_ail, &tmp);
1285 }
1286
1287 - xfs_ail_splice(ailp, &tmp, lsn);
1288 + xfs_ail_splice(ailp, cur, &tmp, lsn);
1289
1290 if (!mlip_changed) {
1291 spin_unlock(&ailp->xa_lock);
1292 @@ -794,9 +865,18 @@ xfs_trans_ail_init(
1293 ailp->xa_mount = mp;
1294 INIT_LIST_HEAD(&ailp->xa_ail);
1295 spin_lock_init(&ailp->xa_lock);
1296 - INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);
1297 +
1298 + ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
1299 + ailp->xa_mount->m_fsname);
1300 + if (IS_ERR(ailp->xa_task))
1301 + goto out_free_ailp;
1302 +
1303 mp->m_ail = ailp;
1304 return 0;
1305 +
1306 +out_free_ailp:
1307 + kmem_free(ailp);
1308 + return ENOMEM;
1309 }
1310
1311 void
1312 @@ -805,6 +885,6 @@ xfs_trans_ail_destroy(
1313 {
1314 struct xfs_ail *ailp = mp->m_ail;
1315
1316 - cancel_delayed_work_sync(&ailp->xa_work);
1317 + kthread_stop(ailp->xa_task);
1318 kmem_free(ailp);
1319 }
1320 diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
1321 index 6b164e9..fe2e3cb 100644
1322 --- a/fs/xfs/xfs_trans_priv.h
1323 +++ b/fs/xfs/xfs_trans_priv.h
1324 @@ -64,24 +64,19 @@ struct xfs_ail_cursor {
1325 */
1326 struct xfs_ail {
1327 struct xfs_mount *xa_mount;
1328 + struct task_struct *xa_task;
1329 struct list_head xa_ail;
1330 xfs_lsn_t xa_target;
1331 struct xfs_ail_cursor xa_cursors;
1332 spinlock_t xa_lock;
1333 - struct delayed_work xa_work;
1334 xfs_lsn_t xa_last_pushed_lsn;
1335 - unsigned long xa_flags;
1336 };
1337
1338 -#define XFS_AIL_PUSHING_BIT 0
1339 -
1340 /*
1341 * From xfs_trans_ail.c
1342 */
1343 -
1344 -extern struct workqueue_struct *xfs_ail_wq; /* AIL workqueue */
1345 -
1346 void xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
1347 + struct xfs_ail_cursor *cur,
1348 struct xfs_log_item **log_items, int nr_items,
1349 xfs_lsn_t lsn) __releases(ailp->xa_lock);
1350 static inline void
1351 @@ -90,7 +85,7 @@ xfs_trans_ail_update(
1352 struct xfs_log_item *lip,
1353 xfs_lsn_t lsn) __releases(ailp->xa_lock)
1354 {
1355 - xfs_trans_ail_update_bulk(ailp, &lip, 1, lsn);
1356 + xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
1357 }
1358
1359 void xfs_trans_ail_delete_bulk(struct xfs_ail *ailp,
1360 @@ -111,10 +106,13 @@ xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp);
1361 void xfs_trans_unlocked_item(struct xfs_ail *,
1362 xfs_log_item_t *);
1363
1364 -struct xfs_log_item *xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
1365 +struct xfs_log_item * xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
1366 + struct xfs_ail_cursor *cur,
1367 + xfs_lsn_t lsn);
1368 +struct xfs_log_item * xfs_trans_ail_cursor_last(struct xfs_ail *ailp,
1369 struct xfs_ail_cursor *cur,
1370 xfs_lsn_t lsn);
1371 -struct xfs_log_item *xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
1372 +struct xfs_log_item * xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
1373 struct xfs_ail_cursor *cur);
1374 void xfs_trans_ail_cursor_done(struct xfs_ail *ailp,
1375 struct xfs_ail_cursor *cur);
1376 diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
1377 index c8008dd..640ded8 100644
1378 --- a/kernel/posix-cpu-timers.c
1379 +++ b/kernel/posix-cpu-timers.c
1380 @@ -274,9 +274,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
1381 struct task_cputime sum;
1382 unsigned long flags;
1383
1384 - spin_lock_irqsave(&cputimer->lock, flags);
1385 if (!cputimer->running) {
1386 - cputimer->running = 1;
1387 /*
1388 * The POSIX timer interface allows for absolute time expiry
1389 * values through the TIMER_ABSTIME flag, therefore we have
1390 @@ -284,8 +282,11 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
1391 * it.
1392 */
1393 thread_group_cputime(tsk, &sum);
1394 + spin_lock_irqsave(&cputimer->lock, flags);
1395 + cputimer->running = 1;
1396 update_gt_cputime(&cputimer->cputime, &sum);
1397 - }
1398 + } else
1399 + spin_lock_irqsave(&cputimer->lock, flags);
1400 *times = cputimer->cputime;
1401 spin_unlock_irqrestore(&cputimer->lock, flags);
1402 }
1403 diff --git a/kernel/sys.c b/kernel/sys.c
1404 index 5c942cf..f88dadc 100644
1405 --- a/kernel/sys.c
1406 +++ b/kernel/sys.c
1407 @@ -1135,7 +1135,7 @@ DECLARE_RWSEM(uts_sem);
1408 static int override_release(char __user *release, int len)
1409 {
1410 int ret = 0;
1411 - char buf[len];
1412 + char buf[65];
1413
1414 if (current->personality & UNAME26) {
1415 char *rest = UTS_RELEASE;
1416 diff --git a/mm/migrate.c b/mm/migrate.c
1417 index 666e4e6..14d0a6a 100644
1418 --- a/mm/migrate.c
1419 +++ b/mm/migrate.c
1420 @@ -120,10 +120,10 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
1421
1422 ptep = pte_offset_map(pmd, addr);
1423
1424 - if (!is_swap_pte(*ptep)) {
1425 - pte_unmap(ptep);
1426 - goto out;
1427 - }
1428 + /*
1429 + * Peek to check is_swap_pte() before taking ptlock? No, we
1430 + * can race mremap's move_ptes(), which skips anon_vma lock.
1431 + */
1432
1433 ptl = pte_lockptr(mm, pmd);
1434 }
1435 diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
1436 index 4680b1e..373e14f 100644
1437 --- a/net/x25/af_x25.c
1438 +++ b/net/x25/af_x25.c
1439 @@ -295,7 +295,8 @@ static struct sock *x25_find_listener(struct x25_address *addr,
1440 * Found a listening socket, now check the incoming
1441 * call user data vs this sockets call user data
1442 */
1443 - if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
1444 + if (x25_sk(s)->cudmatchlength > 0 &&
1445 + skb->len >= x25_sk(s)->cudmatchlength) {
1446 if((memcmp(x25_sk(s)->calluserdata.cuddata,
1447 skb->data,
1448 x25_sk(s)->cudmatchlength)) == 0) {
1449 diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
1450 index 486f6de..981b6fd 100644
1451 --- a/sound/pci/hda/hda_intel.c
1452 +++ b/sound/pci/hda/hda_intel.c
1453 @@ -2352,6 +2352,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
1454 SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
1455 SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
1456 SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
1457 + SND_PCI_QUIRK(0x1028, 0x02c6, "Dell Inspiron 1010", POS_FIX_LPIB),
1458 SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
1459 SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
1460 SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
1461 diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
1462 index 7bbc5f2..cf1fa36 100644
1463 --- a/sound/pci/hda/patch_conexant.c
1464 +++ b/sound/pci/hda/patch_conexant.c
1465 @@ -3097,6 +3097,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
1466 SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
1467 SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
1468 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
1469 + SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO),
1470 SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
1471 SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
1472 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),

  ViewVC Help
Powered by ViewVC 1.1.20