Contents of /trunk/kernel-alx/patches-3.4/0119-3.4.20-all-fixes.patch
Parent Directory | Revision Log
Revision 1973 -
(show annotations)
(download)
Fri Nov 30 10:38:25 2012 UTC (11 years, 9 months ago) by niro
File size: 186405 byte(s)
Fri Nov 30 10:38:25 2012 UTC (11 years, 9 months ago) by niro
File size: 186405 byte(s)
-linux 3.4.20
1 | diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt |
2 | index 9b1067a..68c5411 100644 |
3 | --- a/Documentation/cgroups/memory.txt |
4 | +++ b/Documentation/cgroups/memory.txt |
5 | @@ -466,6 +466,10 @@ Note: |
6 | 5.3 swappiness |
7 | |
8 | Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only. |
9 | +Please note that unlike the global swappiness, memcg knob set to 0 |
10 | +really prevents from any swapping even if there is a swap storage |
11 | +available. This might lead to memcg OOM killer if there are no file |
12 | +pages to reclaim. |
13 | |
14 | Following cgroups' swappiness can't be changed. |
15 | - root cgroup (uses /proc/sys/vm/swappiness). |
16 | diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h |
17 | index c369c9d..9ff4444 100644 |
18 | --- a/arch/arm/plat-omap/include/plat/omap-serial.h |
19 | +++ b/arch/arm/plat-omap/include/plat/omap-serial.h |
20 | @@ -42,10 +42,10 @@ |
21 | #define OMAP_UART_WER_MOD_WKUP 0X7F |
22 | |
23 | /* Enable XON/XOFF flow control on output */ |
24 | -#define OMAP_UART_SW_TX 0x8 |
25 | +#define OMAP_UART_SW_TX 0x04 |
26 | |
27 | /* Enable XON/XOFF flow control on input */ |
28 | -#define OMAP_UART_SW_RX 0x2 |
29 | +#define OMAP_UART_SW_RX 0x04 |
30 | |
31 | #define OMAP_UART_SYSC_RESET 0X07 |
32 | #define OMAP_UART_TCR_TRIG 0X0F |
33 | diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h |
34 | index 60e8866..93fe83e 100644 |
35 | --- a/arch/m68k/include/asm/signal.h |
36 | +++ b/arch/m68k/include/asm/signal.h |
37 | @@ -156,7 +156,7 @@ typedef struct sigaltstack { |
38 | static inline void sigaddset(sigset_t *set, int _sig) |
39 | { |
40 | asm ("bfset %0{%1,#1}" |
41 | - : "+od" (*set) |
42 | + : "+o" (*set) |
43 | : "id" ((_sig - 1) ^ 31) |
44 | : "cc"); |
45 | } |
46 | @@ -164,7 +164,7 @@ static inline void sigaddset(sigset_t *set, int _sig) |
47 | static inline void sigdelset(sigset_t *set, int _sig) |
48 | { |
49 | asm ("bfclr %0{%1,#1}" |
50 | - : "+od" (*set) |
51 | + : "+o" (*set) |
52 | : "id" ((_sig - 1) ^ 31) |
53 | : "cc"); |
54 | } |
55 | @@ -180,7 +180,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig) |
56 | int ret; |
57 | asm ("bfextu %1{%2,#1},%0" |
58 | : "=d" (ret) |
59 | - : "od" (*set), "id" ((_sig-1) ^ 31) |
60 | + : "o" (*set), "id" ((_sig-1) ^ 31) |
61 | : "cc"); |
62 | return ret; |
63 | } |
64 | diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h |
65 | index 234f1d8..2e0a15b 100644 |
66 | --- a/arch/s390/include/asm/compat.h |
67 | +++ b/arch/s390/include/asm/compat.h |
68 | @@ -20,7 +20,7 @@ |
69 | #define PSW32_MASK_CC 0x00003000UL |
70 | #define PSW32_MASK_PM 0x00000f00UL |
71 | |
72 | -#define PSW32_MASK_USER 0x00003F00UL |
73 | +#define PSW32_MASK_USER 0x0000FF00UL |
74 | |
75 | #define PSW32_ADDR_AMODE 0x80000000UL |
76 | #define PSW32_ADDR_INSN 0x7FFFFFFFUL |
77 | diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h |
78 | index aeb77f0..d3750e7 100644 |
79 | --- a/arch/s390/include/asm/ptrace.h |
80 | +++ b/arch/s390/include/asm/ptrace.h |
81 | @@ -240,7 +240,7 @@ typedef struct |
82 | #define PSW_MASK_EA 0x00000000UL |
83 | #define PSW_MASK_BA 0x00000000UL |
84 | |
85 | -#define PSW_MASK_USER 0x00003F00UL |
86 | +#define PSW_MASK_USER 0x0000FF00UL |
87 | |
88 | #define PSW_ADDR_AMODE 0x80000000UL |
89 | #define PSW_ADDR_INSN 0x7FFFFFFFUL |
90 | @@ -269,7 +269,7 @@ typedef struct |
91 | #define PSW_MASK_EA 0x0000000100000000UL |
92 | #define PSW_MASK_BA 0x0000000080000000UL |
93 | |
94 | -#define PSW_MASK_USER 0x00003F0180000000UL |
95 | +#define PSW_MASK_USER 0x0000FF0180000000UL |
96 | |
97 | #define PSW_ADDR_AMODE 0x0000000000000000UL |
98 | #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL |
99 | diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c |
100 | index 28040fd..0bdca3a 100644 |
101 | --- a/arch/s390/kernel/compat_signal.c |
102 | +++ b/arch/s390/kernel/compat_signal.c |
103 | @@ -313,6 +313,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) |
104 | regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | |
105 | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | |
106 | (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); |
107 | + /* Check for invalid user address space control. */ |
108 | + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) |
109 | + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | |
110 | + (regs->psw.mask & ~PSW_MASK_ASC); |
111 | regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); |
112 | for (i = 0; i < NUM_GPRS; i++) |
113 | regs->gprs[i] = (__u64) regs32.gprs[i]; |
114 | @@ -494,7 +498,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka, |
115 | |
116 | /* Set up registers for signal handler */ |
117 | regs->gprs[15] = (__force __u64) frame; |
118 | - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ |
119 | + /* Force 31 bit amode and default user address space control. */ |
120 | + regs->psw.mask = PSW_MASK_BA | |
121 | + (psw_user_bits & PSW_MASK_ASC) | |
122 | + (regs->psw.mask & ~PSW_MASK_ASC); |
123 | regs->psw.addr = (__force __u64) ka->sa.sa_handler; |
124 | |
125 | regs->gprs[2] = map_signal(sig); |
126 | @@ -562,7 +569,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, |
127 | |
128 | /* Set up registers for signal handler */ |
129 | regs->gprs[15] = (__force __u64) frame; |
130 | - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ |
131 | + /* Force 31 bit amode and default user address space control. */ |
132 | + regs->psw.mask = PSW_MASK_BA | |
133 | + (psw_user_bits & PSW_MASK_ASC) | |
134 | + (regs->psw.mask & ~PSW_MASK_ASC); |
135 | regs->psw.addr = (__u64) ka->sa.sa_handler; |
136 | |
137 | regs->gprs[2] = map_signal(sig); |
138 | diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c |
139 | index f7582b2..74f58e2 100644 |
140 | --- a/arch/s390/kernel/signal.c |
141 | +++ b/arch/s390/kernel/signal.c |
142 | @@ -148,6 +148,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) |
143 | /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ |
144 | regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | |
145 | (user_sregs.regs.psw.mask & PSW_MASK_USER); |
146 | + /* Check for invalid user address space control. */ |
147 | + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) |
148 | + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | |
149 | + (regs->psw.mask & ~PSW_MASK_ASC); |
150 | /* Check for invalid amode */ |
151 | if (regs->psw.mask & PSW_MASK_EA) |
152 | regs->psw.mask |= PSW_MASK_BA; |
153 | @@ -294,7 +298,10 @@ static int setup_frame(int sig, struct k_sigaction *ka, |
154 | |
155 | /* Set up registers for signal handler */ |
156 | regs->gprs[15] = (unsigned long) frame; |
157 | - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ |
158 | + /* Force default amode and default user address space control. */ |
159 | + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | |
160 | + (psw_user_bits & PSW_MASK_ASC) | |
161 | + (regs->psw.mask & ~PSW_MASK_ASC); |
162 | regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; |
163 | |
164 | regs->gprs[2] = map_signal(sig); |
165 | @@ -367,7 +374,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
166 | |
167 | /* Set up registers for signal handler */ |
168 | regs->gprs[15] = (unsigned long) frame; |
169 | - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ |
170 | + /* Force default amode and default user address space control. */ |
171 | + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | |
172 | + (psw_user_bits & PSW_MASK_ASC) | |
173 | + (regs->psw.mask & ~PSW_MASK_ASC); |
174 | regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; |
175 | |
176 | regs->gprs[2] = map_signal(sig); |
177 | diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c |
178 | index 65cb06e..4ccf9f5 100644 |
179 | --- a/arch/s390/mm/gup.c |
180 | +++ b/arch/s390/mm/gup.c |
181 | @@ -183,7 +183,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, |
182 | addr = start; |
183 | len = (unsigned long) nr_pages << PAGE_SHIFT; |
184 | end = start + len; |
185 | - if (end < start) |
186 | + if ((end < start) || (end > TASK_SIZE)) |
187 | goto slow_irqon; |
188 | |
189 | /* |
190 | diff --git a/crypto/cryptd.c b/crypto/cryptd.c |
191 | index 671d4d6..7bdd61b 100644 |
192 | --- a/crypto/cryptd.c |
193 | +++ b/crypto/cryptd.c |
194 | @@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work) |
195 | struct crypto_async_request *req, *backlog; |
196 | |
197 | cpu_queue = container_of(work, struct cryptd_cpu_queue, work); |
198 | - /* Only handle one request at a time to avoid hogging crypto |
199 | - * workqueue. preempt_disable/enable is used to prevent |
200 | - * being preempted by cryptd_enqueue_request() */ |
201 | + /* |
202 | + * Only handle one request at a time to avoid hogging crypto workqueue. |
203 | + * preempt_disable/enable is used to prevent being preempted by |
204 | + * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent |
205 | + * cryptd_enqueue_request() being accessed from software interrupts. |
206 | + */ |
207 | + local_bh_disable(); |
208 | preempt_disable(); |
209 | backlog = crypto_get_backlog(&cpu_queue->queue); |
210 | req = crypto_dequeue_request(&cpu_queue->queue); |
211 | preempt_enable(); |
212 | + local_bh_enable(); |
213 | |
214 | if (!req) |
215 | return; |
216 | diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c |
217 | index 48b5a3c..62d9ee6 100644 |
218 | --- a/drivers/acpi/video.c |
219 | +++ b/drivers/acpi/video.c |
220 | @@ -1345,12 +1345,15 @@ static int |
221 | acpi_video_bus_get_devices(struct acpi_video_bus *video, |
222 | struct acpi_device *device) |
223 | { |
224 | - int status; |
225 | + int status = 0; |
226 | struct acpi_device *dev; |
227 | |
228 | - status = acpi_video_device_enumerate(video); |
229 | - if (status) |
230 | - return status; |
231 | + /* |
232 | + * There are systems where video module known to work fine regardless |
233 | + * of broken _DOD and ignoring returned value here doesn't cause |
234 | + * any issues later. |
235 | + */ |
236 | + acpi_video_device_enumerate(video); |
237 | |
238 | list_for_each_entry(dev, &device->children, node) { |
239 | |
240 | diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c |
241 | index 013c7a5..7b33136 100644 |
242 | --- a/drivers/block/rbd.c |
243 | +++ b/drivers/block/rbd.c |
244 | @@ -175,8 +175,7 @@ struct rbd_device { |
245 | /* protects updating the header */ |
246 | struct rw_semaphore header_rwsem; |
247 | char snap_name[RBD_MAX_SNAP_NAME_LEN]; |
248 | - u32 cur_snap; /* index+1 of current snapshot within snap context |
249 | - 0 - for the head */ |
250 | + u64 snap_id; /* current snapshot id */ |
251 | int read_only; |
252 | |
253 | struct list_head node; |
254 | @@ -450,7 +449,9 @@ static void rbd_client_release(struct kref *kref) |
255 | struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); |
256 | |
257 | dout("rbd_release_client %p\n", rbdc); |
258 | + spin_lock(&rbd_client_list_lock); |
259 | list_del(&rbdc->node); |
260 | + spin_unlock(&rbd_client_list_lock); |
261 | |
262 | ceph_destroy_client(rbdc->client); |
263 | kfree(rbdc->rbd_opts); |
264 | @@ -463,9 +464,7 @@ static void rbd_client_release(struct kref *kref) |
265 | */ |
266 | static void rbd_put_client(struct rbd_device *rbd_dev) |
267 | { |
268 | - spin_lock(&rbd_client_list_lock); |
269 | kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); |
270 | - spin_unlock(&rbd_client_list_lock); |
271 | rbd_dev->rbd_client = NULL; |
272 | } |
273 | |
274 | @@ -498,7 +497,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, |
275 | |
276 | snap_count = le32_to_cpu(ondisk->snap_count); |
277 | header->snapc = kmalloc(sizeof(struct ceph_snap_context) + |
278 | - snap_count * sizeof (*ondisk), |
279 | + snap_count * sizeof(u64), |
280 | gfp_flags); |
281 | if (!header->snapc) |
282 | return -ENOMEM; |
283 | @@ -552,21 +551,6 @@ err_snapc: |
284 | return -ENOMEM; |
285 | } |
286 | |
287 | -static int snap_index(struct rbd_image_header *header, int snap_num) |
288 | -{ |
289 | - return header->total_snaps - snap_num; |
290 | -} |
291 | - |
292 | -static u64 cur_snap_id(struct rbd_device *rbd_dev) |
293 | -{ |
294 | - struct rbd_image_header *header = &rbd_dev->header; |
295 | - |
296 | - if (!rbd_dev->cur_snap) |
297 | - return 0; |
298 | - |
299 | - return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)]; |
300 | -} |
301 | - |
302 | static int snap_by_name(struct rbd_image_header *header, const char *snap_name, |
303 | u64 *seq, u64 *size) |
304 | { |
305 | @@ -605,7 +589,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) |
306 | snapc->seq = header->snap_seq; |
307 | else |
308 | snapc->seq = 0; |
309 | - dev->cur_snap = 0; |
310 | + dev->snap_id = CEPH_NOSNAP; |
311 | dev->read_only = 0; |
312 | if (size) |
313 | *size = header->image_size; |
314 | @@ -613,8 +597,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) |
315 | ret = snap_by_name(header, dev->snap_name, &snapc->seq, size); |
316 | if (ret < 0) |
317 | goto done; |
318 | - |
319 | - dev->cur_snap = header->total_snaps - ret; |
320 | + dev->snap_id = snapc->seq; |
321 | dev->read_only = 1; |
322 | } |
323 | |
324 | @@ -1521,7 +1504,7 @@ static void rbd_rq_fn(struct request_queue *q) |
325 | coll, cur_seg); |
326 | else |
327 | rbd_req_read(rq, rbd_dev, |
328 | - cur_snap_id(rbd_dev), |
329 | + rbd_dev->snap_id, |
330 | ofs, |
331 | op_size, bio, |
332 | coll, cur_seg); |
333 | @@ -1656,7 +1639,7 @@ static int rbd_header_add_snap(struct rbd_device *dev, |
334 | struct ceph_mon_client *monc; |
335 | |
336 | /* we should create a snapshot only if we're pointing at the head */ |
337 | - if (dev->cur_snap) |
338 | + if (dev->snap_id != CEPH_NOSNAP) |
339 | return -EINVAL; |
340 | |
341 | monc = &dev->rbd_client->client->monc; |
342 | @@ -1683,7 +1666,9 @@ static int rbd_header_add_snap(struct rbd_device *dev, |
343 | if (ret < 0) |
344 | return ret; |
345 | |
346 | - dev->header.snapc->seq = new_snapid; |
347 | + down_write(&dev->header_rwsem); |
348 | + dev->header.snapc->seq = new_snapid; |
349 | + up_write(&dev->header_rwsem); |
350 | |
351 | return 0; |
352 | bad: |
353 | diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c |
354 | index 80b331c..5ba5e66 100644 |
355 | --- a/drivers/gpu/drm/i915/intel_overlay.c |
356 | +++ b/drivers/gpu/drm/i915/intel_overlay.c |
357 | @@ -427,9 +427,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) |
358 | OUT_RING(flip_addr); |
359 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
360 | /* turn overlay off */ |
361 | - OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); |
362 | - OUT_RING(flip_addr); |
363 | - OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
364 | + if (IS_I830(dev)) { |
365 | + /* Workaround: Don't disable the overlay fully, since otherwise |
366 | + * it dies on the next OVERLAY_ON cmd. */ |
367 | + OUT_RING(MI_NOOP); |
368 | + OUT_RING(MI_NOOP); |
369 | + OUT_RING(MI_NOOP); |
370 | + } else { |
371 | + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); |
372 | + OUT_RING(flip_addr); |
373 | + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
374 | + } |
375 | ADVANCE_LP_RING(); |
376 | |
377 | return intel_overlay_do_wait_request(overlay, request, |
378 | diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c |
379 | index 2d07fbf..f6176bc 100644 |
380 | --- a/drivers/gpu/drm/radeon/atombios_encoders.c |
381 | +++ b/drivers/gpu/drm/radeon/atombios_encoders.c |
382 | @@ -1421,7 +1421,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) |
383 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); |
384 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); |
385 | /* some early dce3.2 boards have a bug in their transmitter control table */ |
386 | - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) |
387 | + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) |
388 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); |
389 | } |
390 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { |
391 | diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c |
392 | index ebc6fac..578207e 100644 |
393 | --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c |
394 | +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c |
395 | @@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, |
396 | /* clear the pages coming from the pool if requested */ |
397 | if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { |
398 | list_for_each_entry(p, &plist, lru) { |
399 | - clear_page(page_address(p)); |
400 | + if (PageHighMem(p)) |
401 | + clear_highpage(p); |
402 | + else |
403 | + clear_page(page_address(p)); |
404 | } |
405 | } |
406 | |
407 | diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c |
408 | index 589753f..2b78ddd 100644 |
409 | --- a/drivers/net/ethernet/marvell/sky2.c |
410 | +++ b/drivers/net/ethernet/marvell/sky2.c |
411 | @@ -3079,8 +3079,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id) |
412 | |
413 | /* Reading this mask interrupts as side effect */ |
414 | status = sky2_read32(hw, B0_Y2_SP_ISRC2); |
415 | - if (status == 0 || status == ~0) |
416 | + if (status == 0 || status == ~0) { |
417 | + sky2_write32(hw, B0_Y2_SP_ICR, 2); |
418 | return IRQ_NONE; |
419 | + } |
420 | |
421 | prefetch(&hw->st_le[hw->st_idx]); |
422 | |
423 | diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c |
424 | index 482dcd3..0dc70c2 100644 |
425 | --- a/drivers/net/ethernet/realtek/r8169.c |
426 | +++ b/drivers/net/ethernet/realtek/r8169.c |
427 | @@ -73,7 +73,7 @@ |
428 | static const int multicast_filter_limit = 32; |
429 | |
430 | #define MAX_READ_REQUEST_SHIFT 12 |
431 | -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ |
432 | +#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ |
433 | #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ |
434 | #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ |
435 | |
436 | @@ -3488,6 +3488,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) |
437 | void __iomem *ioaddr = tp->mmio_addr; |
438 | |
439 | switch (tp->mac_version) { |
440 | + case RTL_GIGA_MAC_VER_25: |
441 | + case RTL_GIGA_MAC_VER_26: |
442 | case RTL_GIGA_MAC_VER_29: |
443 | case RTL_GIGA_MAC_VER_30: |
444 | case RTL_GIGA_MAC_VER_32: |
445 | @@ -4129,6 +4131,9 @@ static void rtl_set_rx_mode(struct net_device *dev) |
446 | mc_filter[1] = swab32(data); |
447 | } |
448 | |
449 | + if (tp->mac_version == RTL_GIGA_MAC_VER_35) |
450 | + mc_filter[1] = mc_filter[0] = 0xffffffff; |
451 | + |
452 | RTL_W32(MAR0 + 4, mc_filter[1]); |
453 | RTL_W32(MAR0 + 0, mc_filter[0]); |
454 | |
455 | diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h |
456 | index 66b6e3d..6eecbde 100644 |
457 | --- a/drivers/staging/android/android_alarm.h |
458 | +++ b/drivers/staging/android/android_alarm.h |
459 | @@ -110,12 +110,10 @@ enum android_alarm_return_flags { |
460 | #define ANDROID_ALARM_WAIT _IO('a', 1) |
461 | |
462 | #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) |
463 | -#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) |
464 | - |
465 | /* Set alarm */ |
466 | #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) |
467 | #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) |
468 | -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) |
469 | +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) |
470 | #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) |
471 | #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) |
472 | #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) |
473 | diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c |
474 | index 6189923..d00b38e 100644 |
475 | --- a/drivers/tty/serial/omap-serial.c |
476 | +++ b/drivers/tty/serial/omap-serial.c |
477 | @@ -649,19 +649,19 @@ serial_omap_configure_xonxoff |
478 | |
479 | /* |
480 | * IXON Flag: |
481 | - * Flow control for OMAP.TX |
482 | - * OMAP.RX should listen for XON/XOFF |
483 | + * Enable XON/XOFF flow control on output. |
484 | + * Transmit XON1, XOFF1 |
485 | */ |
486 | if (termios->c_iflag & IXON) |
487 | - up->efr |= OMAP_UART_SW_RX; |
488 | + up->efr |= OMAP_UART_SW_TX; |
489 | |
490 | /* |
491 | * IXOFF Flag: |
492 | - * Flow control for OMAP.RX |
493 | - * OMAP.TX should send XON/XOFF |
494 | + * Enable XON/XOFF flow control on input. |
495 | + * Receiver compares XON1, XOFF1. |
496 | */ |
497 | if (termios->c_iflag & IXOFF) |
498 | - up->efr |= OMAP_UART_SW_TX; |
499 | + up->efr |= OMAP_UART_SW_RX; |
500 | |
501 | serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); |
502 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); |
503 | diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c |
504 | index 17ec21e..43aa36b 100644 |
505 | --- a/drivers/usb/serial/option.c |
506 | +++ b/drivers/usb/serial/option.c |
507 | @@ -157,6 +157,7 @@ static void option_instat_callback(struct urb *urb); |
508 | #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 |
509 | #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 |
510 | #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 |
511 | +#define NOVATELWIRELESS_PRODUCT_E362 0x9010 |
512 | #define NOVATELWIRELESS_PRODUCT_G1 0xA001 |
513 | #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 |
514 | #define NOVATELWIRELESS_PRODUCT_G2 0xA010 |
515 | @@ -192,6 +193,9 @@ static void option_instat_callback(struct urb *urb); |
516 | #define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181 |
517 | #define DELL_PRODUCT_5730_MINICARD_VZW 0x8182 |
518 | |
519 | +#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ |
520 | +#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ |
521 | + |
522 | #define KYOCERA_VENDOR_ID 0x0c88 |
523 | #define KYOCERA_PRODUCT_KPC650 0x17da |
524 | #define KYOCERA_PRODUCT_KPC680 0x180a |
525 | @@ -282,6 +286,7 @@ static void option_instat_callback(struct urb *urb); |
526 | /* ALCATEL PRODUCTS */ |
527 | #define ALCATEL_VENDOR_ID 0x1bbb |
528 | #define ALCATEL_PRODUCT_X060S_X200 0x0000 |
529 | +#define ALCATEL_PRODUCT_X220_X500D 0x0017 |
530 | |
531 | #define PIRELLI_VENDOR_ID 0x1266 |
532 | #define PIRELLI_PRODUCT_C100_1 0x1002 |
533 | @@ -705,6 +710,7 @@ static const struct usb_device_id option_ids[] = { |
534 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, |
535 | /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ |
536 | { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, |
537 | + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, |
538 | |
539 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, |
540 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, |
541 | @@ -727,6 +733,8 @@ static const struct usb_device_id option_ids[] = { |
542 | { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ |
543 | { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ |
544 | { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ |
545 | + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, |
546 | + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, |
547 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ |
548 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, |
549 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, |
550 | @@ -1156,6 +1164,7 @@ static const struct usb_device_id option_ids[] = { |
551 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), |
552 | .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist |
553 | }, |
554 | + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, |
555 | { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, |
556 | { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, |
557 | { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), |
558 | diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c |
559 | index bcf2617..c627ba2 100644 |
560 | --- a/drivers/usb/serial/usb-serial.c |
561 | +++ b/drivers/usb/serial/usb-serial.c |
562 | @@ -768,7 +768,7 @@ int usb_serial_probe(struct usb_interface *interface, |
563 | |
564 | if (retval) { |
565 | dbg("sub driver rejected device"); |
566 | - kfree(serial); |
567 | + usb_serial_put(serial); |
568 | module_put(type->driver.owner); |
569 | return retval; |
570 | } |
571 | @@ -840,7 +840,7 @@ int usb_serial_probe(struct usb_interface *interface, |
572 | */ |
573 | if (num_bulk_in == 0 || num_bulk_out == 0) { |
574 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); |
575 | - kfree(serial); |
576 | + usb_serial_put(serial); |
577 | module_put(type->driver.owner); |
578 | return -ENODEV; |
579 | } |
580 | @@ -854,7 +854,7 @@ int usb_serial_probe(struct usb_interface *interface, |
581 | if (num_ports == 0) { |
582 | dev_err(&interface->dev, |
583 | "Generic device with no bulk out, not allowed.\n"); |
584 | - kfree(serial); |
585 | + usb_serial_put(serial); |
586 | module_put(type->driver.owner); |
587 | return -EIO; |
588 | } |
589 | diff --git a/drivers/xen/events.c b/drivers/xen/events.c |
590 | index 6908e4c..26c47a4 100644 |
591 | --- a/drivers/xen/events.c |
592 | +++ b/drivers/xen/events.c |
593 | @@ -1365,8 +1365,8 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) |
594 | { |
595 | struct pt_regs *old_regs = set_irq_regs(regs); |
596 | |
597 | - exit_idle(); |
598 | irq_enter(); |
599 | + exit_idle(); |
600 | |
601 | __xen_evtchn_do_upcall(); |
602 | |
603 | diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c |
604 | index 173b1d2..32ee086 100644 |
605 | --- a/fs/ceph/addr.c |
606 | +++ b/fs/ceph/addr.c |
607 | @@ -54,7 +54,12 @@ |
608 | (CONGESTION_ON_THRESH(congestion_kb) - \ |
609 | (CONGESTION_ON_THRESH(congestion_kb) >> 2)) |
610 | |
611 | - |
612 | +static inline struct ceph_snap_context *page_snap_context(struct page *page) |
613 | +{ |
614 | + if (PagePrivate(page)) |
615 | + return (void *)page->private; |
616 | + return NULL; |
617 | +} |
618 | |
619 | /* |
620 | * Dirty a page. Optimistically adjust accounting, on the assumption |
621 | @@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct page *page, unsigned long offset) |
622 | { |
623 | struct inode *inode; |
624 | struct ceph_inode_info *ci; |
625 | - struct ceph_snap_context *snapc = (void *)page->private; |
626 | + struct ceph_snap_context *snapc = page_snap_context(page); |
627 | |
628 | BUG_ON(!PageLocked(page)); |
629 | - BUG_ON(!page->private); |
630 | BUG_ON(!PagePrivate(page)); |
631 | BUG_ON(!page->mapping); |
632 | |
633 | @@ -182,7 +186,6 @@ static int ceph_releasepage(struct page *page, gfp_t g) |
634 | struct inode *inode = page->mapping ? page->mapping->host : NULL; |
635 | dout("%p releasepage %p idx %lu\n", inode, page, page->index); |
636 | WARN_ON(PageDirty(page)); |
637 | - WARN_ON(page->private); |
638 | WARN_ON(PagePrivate(page)); |
639 | return 0; |
640 | } |
641 | @@ -202,7 +205,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) |
642 | dout("readpage inode %p file %p page %p index %lu\n", |
643 | inode, filp, page, page->index); |
644 | err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, |
645 | - page->index << PAGE_CACHE_SHIFT, &len, |
646 | + (u64) page_offset(page), &len, |
647 | ci->i_truncate_seq, ci->i_truncate_size, |
648 | &page, 1, 0); |
649 | if (err == -ENOENT) |
650 | @@ -283,7 +286,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) |
651 | int nr_pages = 0; |
652 | int ret; |
653 | |
654 | - off = page->index << PAGE_CACHE_SHIFT; |
655 | + off = (u64) page_offset(page); |
656 | |
657 | /* count pages */ |
658 | next_index = page->index; |
659 | @@ -423,7 +426,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) |
660 | struct ceph_inode_info *ci; |
661 | struct ceph_fs_client *fsc; |
662 | struct ceph_osd_client *osdc; |
663 | - loff_t page_off = page->index << PAGE_CACHE_SHIFT; |
664 | + loff_t page_off = page_offset(page); |
665 | int len = PAGE_CACHE_SIZE; |
666 | loff_t i_size; |
667 | int err = 0; |
668 | @@ -443,7 +446,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) |
669 | osdc = &fsc->client->osdc; |
670 | |
671 | /* verify this is a writeable snap context */ |
672 | - snapc = (void *)page->private; |
673 | + snapc = page_snap_context(page); |
674 | if (snapc == NULL) { |
675 | dout("writepage %p page %p not dirty?\n", inode, page); |
676 | goto out; |
677 | @@ -451,7 +454,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) |
678 | oldest = get_oldest_context(inode, &snap_size); |
679 | if (snapc->seq > oldest->seq) { |
680 | dout("writepage %p page %p snapc %p not writeable - noop\n", |
681 | - inode, page, (void *)page->private); |
682 | + inode, page, snapc); |
683 | /* we should only noop if called by kswapd */ |
684 | WARN_ON((current->flags & PF_MEMALLOC) == 0); |
685 | ceph_put_snap_context(oldest); |
686 | @@ -591,7 +594,7 @@ static void writepages_finish(struct ceph_osd_request *req, |
687 | clear_bdi_congested(&fsc->backing_dev_info, |
688 | BLK_RW_ASYNC); |
689 | |
690 | - ceph_put_snap_context((void *)page->private); |
691 | + ceph_put_snap_context(page_snap_context(page)); |
692 | page->private = 0; |
693 | ClearPagePrivate(page); |
694 | dout("unlocking %d %p\n", i, page); |
695 | @@ -795,7 +798,7 @@ get_more_pages: |
696 | } |
697 | |
698 | /* only if matching snap context */ |
699 | - pgsnapc = (void *)page->private; |
700 | + pgsnapc = page_snap_context(page); |
701 | if (pgsnapc->seq > snapc->seq) { |
702 | dout("page snapc %p %lld > oldest %p %lld\n", |
703 | pgsnapc, pgsnapc->seq, snapc, snapc->seq); |
704 | @@ -814,8 +817,7 @@ get_more_pages: |
705 | /* ok */ |
706 | if (locked_pages == 0) { |
707 | /* prepare async write request */ |
708 | - offset = (unsigned long long)page->index |
709 | - << PAGE_CACHE_SHIFT; |
710 | + offset = (u64) page_offset(page); |
711 | len = wsize; |
712 | req = ceph_osdc_new_request(&fsc->client->osdc, |
713 | &ci->i_layout, |
714 | @@ -984,7 +986,7 @@ retry_locked: |
715 | BUG_ON(!ci->i_snap_realm); |
716 | down_read(&mdsc->snap_rwsem); |
717 | BUG_ON(!ci->i_snap_realm->cached_context); |
718 | - snapc = (void *)page->private; |
719 | + snapc = page_snap_context(page); |
720 | if (snapc && snapc != ci->i_head_snapc) { |
721 | /* |
722 | * this page is already dirty in another (older) snap |
723 | @@ -1177,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
724 | struct inode *inode = vma->vm_file->f_dentry->d_inode; |
725 | struct page *page = vmf->page; |
726 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; |
727 | - loff_t off = page->index << PAGE_CACHE_SHIFT; |
728 | + loff_t off = page_offset(page); |
729 | loff_t size, len; |
730 | int ret; |
731 | |
732 | diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c |
733 | index fb962ef..6d59006 100644 |
734 | --- a/fs/ceph/debugfs.c |
735 | +++ b/fs/ceph/debugfs.c |
736 | @@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) |
737 | int err = -ENOMEM; |
738 | |
739 | dout("ceph_fs_debugfs_init\n"); |
740 | + BUG_ON(!fsc->client->debugfs_dir); |
741 | fsc->debugfs_congestion_kb = |
742 | debugfs_create_file("writeback_congestion_kb", |
743 | 0600, |
744 | diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c |
745 | index 89971e1..7f1682d 100644 |
746 | --- a/fs/ceph/mds_client.c |
747 | +++ b/fs/ceph/mds_client.c |
748 | @@ -334,10 +334,10 @@ void ceph_put_mds_session(struct ceph_mds_session *s) |
749 | dout("mdsc put_session %p %d -> %d\n", s, |
750 | atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1); |
751 | if (atomic_dec_and_test(&s->s_ref)) { |
752 | - if (s->s_authorizer) |
753 | + if (s->s_auth.authorizer) |
754 | s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer( |
755 | s->s_mdsc->fsc->client->monc.auth, |
756 | - s->s_authorizer); |
757 | + s->s_auth.authorizer); |
758 | kfree(s); |
759 | } |
760 | } |
761 | @@ -394,11 +394,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, |
762 | s->s_seq = 0; |
763 | mutex_init(&s->s_mutex); |
764 | |
765 | - ceph_con_init(mdsc->fsc->client->msgr, &s->s_con); |
766 | - s->s_con.private = s; |
767 | - s->s_con.ops = &mds_con_ops; |
768 | - s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; |
769 | - s->s_con.peer_name.num = cpu_to_le64(mds); |
770 | + ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr); |
771 | |
772 | spin_lock_init(&s->s_gen_ttl_lock); |
773 | s->s_cap_gen = 0; |
774 | @@ -440,7 +436,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, |
775 | mdsc->sessions[mds] = s; |
776 | atomic_inc(&s->s_ref); /* one ref to sessions[], one to caller */ |
777 | |
778 | - ceph_con_open(&s->s_con, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); |
779 | + ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds, |
780 | + ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); |
781 | |
782 | return s; |
783 | |
784 | @@ -2532,6 +2529,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, |
785 | session->s_seq = 0; |
786 | |
787 | ceph_con_open(&session->s_con, |
788 | + CEPH_ENTITY_TYPE_MDS, mds, |
789 | ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); |
790 | |
791 | /* replay unsafe requests */ |
792 | @@ -2636,7 +2634,8 @@ static void check_new_map(struct ceph_mds_client *mdsc, |
793 | ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "", |
794 | session_state_name(s->s_state)); |
795 | |
796 | - if (memcmp(ceph_mdsmap_get_addr(oldmap, i), |
797 | + if (i >= newmap->m_max_mds || |
798 | + memcmp(ceph_mdsmap_get_addr(oldmap, i), |
799 | ceph_mdsmap_get_addr(newmap, i), |
800 | sizeof(struct ceph_entity_addr))) { |
801 | if (s->s_state == CEPH_MDS_SESSION_OPENING) { |
802 | @@ -3395,39 +3394,33 @@ out: |
803 | /* |
804 | * authentication |
805 | */ |
806 | -static int get_authorizer(struct ceph_connection *con, |
807 | - void **buf, int *len, int *proto, |
808 | - void **reply_buf, int *reply_len, int force_new) |
809 | + |
810 | +/* |
811 | + * Note: returned pointer is the address of a structure that's |
812 | + * managed separately. Caller must *not* attempt to free it. |
813 | + */ |
814 | +static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, |
815 | + int *proto, int force_new) |
816 | { |
817 | struct ceph_mds_session *s = con->private; |
818 | struct ceph_mds_client *mdsc = s->s_mdsc; |
819 | struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; |
820 | - int ret = 0; |
821 | - |
822 | - if (force_new && s->s_authorizer) { |
823 | - ac->ops->destroy_authorizer(ac, s->s_authorizer); |
824 | - s->s_authorizer = NULL; |
825 | - } |
826 | - if (s->s_authorizer == NULL) { |
827 | - if (ac->ops->create_authorizer) { |
828 | - ret = ac->ops->create_authorizer( |
829 | - ac, CEPH_ENTITY_TYPE_MDS, |
830 | - &s->s_authorizer, |
831 | - &s->s_authorizer_buf, |
832 | - &s->s_authorizer_buf_len, |
833 | - &s->s_authorizer_reply_buf, |
834 | - &s->s_authorizer_reply_buf_len); |
835 | - if (ret) |
836 | - return ret; |
837 | - } |
838 | - } |
839 | + struct ceph_auth_handshake *auth = &s->s_auth; |
840 | |
841 | + if (force_new && auth->authorizer) { |
842 | + if (ac->ops && ac->ops->destroy_authorizer) |
843 | + ac->ops->destroy_authorizer(ac, auth->authorizer); |
844 | + auth->authorizer = NULL; |
845 | + } |
846 | + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { |
847 | + int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, |
848 | + auth); |
849 | + if (ret) |
850 | + return ERR_PTR(ret); |
851 | + } |
852 | *proto = ac->protocol; |
853 | - *buf = s->s_authorizer_buf; |
854 | - *len = s->s_authorizer_buf_len; |
855 | - *reply_buf = s->s_authorizer_reply_buf; |
856 | - *reply_len = s->s_authorizer_reply_buf_len; |
857 | - return 0; |
858 | + |
859 | + return auth; |
860 | } |
861 | |
862 | |
863 | @@ -3437,7 +3430,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) |
864 | struct ceph_mds_client *mdsc = s->s_mdsc; |
865 | struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; |
866 | |
867 | - return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len); |
868 | + return ac->ops->verify_authorizer_reply(ac, s->s_auth.authorizer, len); |
869 | } |
870 | |
871 | static int invalidate_authorizer(struct ceph_connection *con) |
872 | diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h |
873 | index 8c7c04e..dd26846 100644 |
874 | --- a/fs/ceph/mds_client.h |
875 | +++ b/fs/ceph/mds_client.h |
876 | @@ -11,6 +11,7 @@ |
877 | #include <linux/ceph/types.h> |
878 | #include <linux/ceph/messenger.h> |
879 | #include <linux/ceph/mdsmap.h> |
880 | +#include <linux/ceph/auth.h> |
881 | |
882 | /* |
883 | * Some lock dependencies: |
884 | @@ -113,9 +114,7 @@ struct ceph_mds_session { |
885 | |
886 | struct ceph_connection s_con; |
887 | |
888 | - struct ceph_authorizer *s_authorizer; |
889 | - void *s_authorizer_buf, *s_authorizer_reply_buf; |
890 | - size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; |
891 | + struct ceph_auth_handshake s_auth; |
892 | |
893 | /* protected by s_gen_ttl_lock */ |
894 | spinlock_t s_gen_ttl_lock; |
895 | diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c |
896 | index 3cc1b25..6ccf176 100644 |
897 | --- a/fs/cifs/cifsacl.c |
898 | +++ b/fs/cifs/cifsacl.c |
899 | @@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr) |
900 | } |
901 | |
902 | static void |
903 | +cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) |
904 | +{ |
905 | + memcpy(dst, src, sizeof(*dst)); |
906 | + dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); |
907 | +} |
908 | + |
909 | +static void |
910 | id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, |
911 | struct cifs_sid_id **psidid, char *typestr) |
912 | { |
913 | @@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, |
914 | } |
915 | } |
916 | |
917 | - memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); |
918 | + cifs_copy_sid(&(*psidid)->sid, sidptr); |
919 | (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); |
920 | (*psidid)->refcount = 0; |
921 | |
922 | @@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) |
923 | * any fields of the node after a reference is put . |
924 | */ |
925 | if (test_bit(SID_ID_MAPPED, &psidid->state)) { |
926 | - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); |
927 | + cifs_copy_sid(ssid, &psidid->sid); |
928 | psidid->time = jiffies; /* update ts for accessing */ |
929 | goto id_sid_out; |
930 | } |
931 | @@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) |
932 | if (IS_ERR(sidkey)) { |
933 | rc = -EINVAL; |
934 | cFYI(1, "%s: Can't map and id to a SID", __func__); |
935 | + } else if (sidkey->datalen < sizeof(struct cifs_sid)) { |
936 | + rc = -EIO; |
937 | + cFYI(1, "%s: Downcall contained malformed key " |
938 | + "(datalen=%hu)", __func__, sidkey->datalen); |
939 | } else { |
940 | lsid = (struct cifs_sid *)sidkey->payload.data; |
941 | - memcpy(&psidid->sid, lsid, |
942 | - sidkey->datalen < sizeof(struct cifs_sid) ? |
943 | - sidkey->datalen : sizeof(struct cifs_sid)); |
944 | - memcpy(ssid, &psidid->sid, |
945 | - sidkey->datalen < sizeof(struct cifs_sid) ? |
946 | - sidkey->datalen : sizeof(struct cifs_sid)); |
947 | + cifs_copy_sid(&psidid->sid, lsid); |
948 | + cifs_copy_sid(ssid, &psidid->sid); |
949 | set_bit(SID_ID_MAPPED, &psidid->state); |
950 | key_put(sidkey); |
951 | kfree(psidid->sidstr); |
952 | @@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) |
953 | return rc; |
954 | } |
955 | if (test_bit(SID_ID_MAPPED, &psidid->state)) |
956 | - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); |
957 | + cifs_copy_sid(ssid, &psidid->sid); |
958 | else |
959 | rc = -EINVAL; |
960 | } |
961 | @@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) |
962 | static void copy_sec_desc(const struct cifs_ntsd *pntsd, |
963 | struct cifs_ntsd *pnntsd, __u32 sidsoffset) |
964 | { |
965 | - int i; |
966 | - |
967 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
968 | struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; |
969 | |
970 | @@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd, |
971 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
972 | le32_to_cpu(pntsd->osidoffset)); |
973 | nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); |
974 | - |
975 | - nowner_sid_ptr->revision = owner_sid_ptr->revision; |
976 | - nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; |
977 | - for (i = 0; i < 6; i++) |
978 | - nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; |
979 | - for (i = 0; i < 5; i++) |
980 | - nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; |
981 | + cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); |
982 | |
983 | /* copy group sid */ |
984 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
985 | le32_to_cpu(pntsd->gsidoffset)); |
986 | ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + |
987 | sizeof(struct cifs_sid)); |
988 | - |
989 | - ngroup_sid_ptr->revision = group_sid_ptr->revision; |
990 | - ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; |
991 | - for (i = 0; i < 6; i++) |
992 | - ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; |
993 | - for (i = 0; i < 5; i++) |
994 | - ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; |
995 | + cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); |
996 | |
997 | return; |
998 | } |
999 | @@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, |
1000 | kfree(nowner_sid_ptr); |
1001 | return rc; |
1002 | } |
1003 | - memcpy(owner_sid_ptr, nowner_sid_ptr, |
1004 | - sizeof(struct cifs_sid)); |
1005 | + cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); |
1006 | kfree(nowner_sid_ptr); |
1007 | *aclflag = CIFS_ACL_OWNER; |
1008 | } |
1009 | @@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, |
1010 | kfree(ngroup_sid_ptr); |
1011 | return rc; |
1012 | } |
1013 | - memcpy(group_sid_ptr, ngroup_sid_ptr, |
1014 | - sizeof(struct cifs_sid)); |
1015 | + cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); |
1016 | kfree(ngroup_sid_ptr); |
1017 | *aclflag = CIFS_ACL_GROUP; |
1018 | } |
1019 | diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c |
1020 | index 0f04d2e..240832e 100644 |
1021 | --- a/fs/ecryptfs/main.c |
1022 | +++ b/fs/ecryptfs/main.c |
1023 | @@ -280,6 +280,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, |
1024 | char *fnek_src; |
1025 | char *cipher_key_bytes_src; |
1026 | char *fn_cipher_key_bytes_src; |
1027 | + u8 cipher_code; |
1028 | |
1029 | *check_ruid = 0; |
1030 | |
1031 | @@ -421,6 +422,18 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, |
1032 | && !fn_cipher_key_bytes_set) |
1033 | mount_crypt_stat->global_default_fn_cipher_key_bytes = |
1034 | mount_crypt_stat->global_default_cipher_key_size; |
1035 | + |
1036 | + cipher_code = ecryptfs_code_for_cipher_string( |
1037 | + mount_crypt_stat->global_default_cipher_name, |
1038 | + mount_crypt_stat->global_default_cipher_key_size); |
1039 | + if (!cipher_code) { |
1040 | + ecryptfs_printk(KERN_ERR, |
1041 | + "eCryptfs doesn't support cipher: %s", |
1042 | + mount_crypt_stat->global_default_cipher_name); |
1043 | + rc = -EINVAL; |
1044 | + goto out; |
1045 | + } |
1046 | + |
1047 | mutex_lock(&key_tfm_list_mutex); |
1048 | if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name, |
1049 | NULL)) { |
1050 | @@ -506,7 +519,6 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags |
1051 | goto out; |
1052 | } |
1053 | |
1054 | - s->s_flags = flags; |
1055 | rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); |
1056 | if (rc) |
1057 | goto out1; |
1058 | @@ -542,6 +554,15 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags |
1059 | } |
1060 | |
1061 | ecryptfs_set_superblock_lower(s, path.dentry->d_sb); |
1062 | + |
1063 | + /** |
1064 | + * Set the POSIX ACL flag based on whether they're enabled in the lower |
1065 | + * mount. Force a read-only eCryptfs mount if the lower mount is ro. |
1066 | + * Allow a ro eCryptfs mount even when the lower mount is rw. |
1067 | + */ |
1068 | + s->s_flags = flags & ~MS_POSIXACL; |
1069 | + s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); |
1070 | + |
1071 | s->s_maxbytes = path.dentry->d_sb->s_maxbytes; |
1072 | s->s_blocksize = path.dentry->d_sb->s_blocksize; |
1073 | s->s_magic = ECRYPTFS_SUPER_MAGIC; |
1074 | diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c |
1075 | index 5e80180..8955e36 100644 |
1076 | --- a/fs/nfs/nfs4proc.c |
1077 | +++ b/fs/nfs/nfs4proc.c |
1078 | @@ -307,8 +307,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc |
1079 | dprintk("%s ERROR: %d Reset session\n", __func__, |
1080 | errorcode); |
1081 | nfs4_schedule_session_recovery(clp->cl_session); |
1082 | - exception->retry = 1; |
1083 | - break; |
1084 | + goto wait_on_recovery; |
1085 | #endif /* defined(CONFIG_NFS_V4_1) */ |
1086 | case -NFS4ERR_FILE_OPEN: |
1087 | if (exception->timeout > HZ) { |
1088 | diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c |
1089 | index f35794b..a506360 100644 |
1090 | --- a/fs/notify/fanotify/fanotify.c |
1091 | +++ b/fs/notify/fanotify/fanotify.c |
1092 | @@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) |
1093 | if ((old->path.mnt == new->path.mnt) && |
1094 | (old->path.dentry == new->path.dentry)) |
1095 | return true; |
1096 | + break; |
1097 | case (FSNOTIFY_EVENT_NONE): |
1098 | return true; |
1099 | default: |
1100 | diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c |
1101 | index f99c1b4..c11db51 100644 |
1102 | --- a/fs/reiserfs/inode.c |
1103 | +++ b/fs/reiserfs/inode.c |
1104 | @@ -1788,8 +1788,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, |
1105 | |
1106 | BUG_ON(!th->t_trans_id); |
1107 | |
1108 | - dquot_initialize(inode); |
1109 | + reiserfs_write_unlock(inode->i_sb); |
1110 | err = dquot_alloc_inode(inode); |
1111 | + reiserfs_write_lock(inode->i_sb); |
1112 | if (err) |
1113 | goto out_end_trans; |
1114 | if (!dir->i_nlink) { |
1115 | @@ -1985,8 +1986,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, |
1116 | |
1117 | out_end_trans: |
1118 | journal_end(th, th->t_super, th->t_blocks_allocated); |
1119 | + reiserfs_write_unlock(inode->i_sb); |
1120 | /* Drop can be outside and it needs more credits so it's better to have it outside */ |
1121 | dquot_drop(inode); |
1122 | + reiserfs_write_lock(inode->i_sb); |
1123 | inode->i_flags |= S_NOQUOTA; |
1124 | make_bad_inode(inode); |
1125 | |
1126 | @@ -3109,10 +3112,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) |
1127 | /* must be turned off for recursive notify_change calls */ |
1128 | ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); |
1129 | |
1130 | - depth = reiserfs_write_lock_once(inode->i_sb); |
1131 | if (is_quota_modification(inode, attr)) |
1132 | dquot_initialize(inode); |
1133 | - |
1134 | + depth = reiserfs_write_lock_once(inode->i_sb); |
1135 | if (attr->ia_valid & ATTR_SIZE) { |
1136 | /* version 2 items will be caught by the s_maxbytes check |
1137 | ** done for us in vmtruncate |
1138 | @@ -3176,7 +3178,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) |
1139 | error = journal_begin(&th, inode->i_sb, jbegin_count); |
1140 | if (error) |
1141 | goto out; |
1142 | + reiserfs_write_unlock_once(inode->i_sb, depth); |
1143 | error = dquot_transfer(inode, attr); |
1144 | + depth = reiserfs_write_lock_once(inode->i_sb); |
1145 | if (error) { |
1146 | journal_end(&th, inode->i_sb, jbegin_count); |
1147 | goto out; |
1148 | diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c |
1149 | index f8afa4b..2f40a4c 100644 |
1150 | --- a/fs/reiserfs/stree.c |
1151 | +++ b/fs/reiserfs/stree.c |
1152 | @@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree |
1153 | key2type(&(key->on_disk_key))); |
1154 | #endif |
1155 | |
1156 | + reiserfs_write_unlock(inode->i_sb); |
1157 | retval = dquot_alloc_space_nodirty(inode, pasted_size); |
1158 | + reiserfs_write_lock(inode->i_sb); |
1159 | if (retval) { |
1160 | pathrelse(search_path); |
1161 | return retval; |
1162 | @@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, |
1163 | "reiserquota insert_item(): allocating %u id=%u type=%c", |
1164 | quota_bytes, inode->i_uid, head2type(ih)); |
1165 | #endif |
1166 | + reiserfs_write_unlock(inode->i_sb); |
1167 | /* We can't dirty inode here. It would be immediately written but |
1168 | * appropriate stat item isn't inserted yet... */ |
1169 | retval = dquot_alloc_space_nodirty(inode, quota_bytes); |
1170 | + reiserfs_write_lock(inode->i_sb); |
1171 | if (retval) { |
1172 | pathrelse(path); |
1173 | return retval; |
1174 | diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c |
1175 | index 8b7616e..8169be9 100644 |
1176 | --- a/fs/reiserfs/super.c |
1177 | +++ b/fs/reiserfs/super.c |
1178 | @@ -256,7 +256,9 @@ static int finish_unfinished(struct super_block *s) |
1179 | retval = remove_save_link_only(s, &save_link_key, 0); |
1180 | continue; |
1181 | } |
1182 | + reiserfs_write_unlock(s); |
1183 | dquot_initialize(inode); |
1184 | + reiserfs_write_lock(s); |
1185 | |
1186 | if (truncate && S_ISDIR(inode->i_mode)) { |
1187 | /* We got a truncate request for a dir which is impossible. |
1188 | @@ -1292,7 +1294,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1189 | kfree(qf_names[i]); |
1190 | #endif |
1191 | err = -EINVAL; |
1192 | - goto out_err; |
1193 | + goto out_unlock; |
1194 | } |
1195 | #ifdef CONFIG_QUOTA |
1196 | handle_quota_files(s, qf_names, &qfmt); |
1197 | @@ -1336,7 +1338,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1198 | if (blocks) { |
1199 | err = reiserfs_resize(s, blocks); |
1200 | if (err != 0) |
1201 | - goto out_err; |
1202 | + goto out_unlock; |
1203 | } |
1204 | |
1205 | if (*mount_flags & MS_RDONLY) { |
1206 | @@ -1346,9 +1348,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1207 | /* it is read-only already */ |
1208 | goto out_ok; |
1209 | |
1210 | + /* |
1211 | + * Drop write lock. Quota will retake it when needed and lock |
1212 | + * ordering requires calling dquot_suspend() without it. |
1213 | + */ |
1214 | + reiserfs_write_unlock(s); |
1215 | err = dquot_suspend(s, -1); |
1216 | if (err < 0) |
1217 | goto out_err; |
1218 | + reiserfs_write_lock(s); |
1219 | |
1220 | /* try to remount file system with read-only permissions */ |
1221 | if (sb_umount_state(rs) == REISERFS_VALID_FS |
1222 | @@ -1358,7 +1366,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1223 | |
1224 | err = journal_begin(&th, s, 10); |
1225 | if (err) |
1226 | - goto out_err; |
1227 | + goto out_unlock; |
1228 | |
1229 | /* Mounting a rw partition read-only. */ |
1230 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); |
1231 | @@ -1373,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1232 | |
1233 | if (reiserfs_is_journal_aborted(journal)) { |
1234 | err = journal->j_errno; |
1235 | - goto out_err; |
1236 | + goto out_unlock; |
1237 | } |
1238 | |
1239 | handle_data_mode(s, mount_options); |
1240 | @@ -1382,7 +1390,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1241 | s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ |
1242 | err = journal_begin(&th, s, 10); |
1243 | if (err) |
1244 | - goto out_err; |
1245 | + goto out_unlock; |
1246 | |
1247 | /* Mount a partition which is read-only, read-write */ |
1248 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); |
1249 | @@ -1399,11 +1407,17 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
1250 | SB_JOURNAL(s)->j_must_wait = 1; |
1251 | err = journal_end(&th, s, 10); |
1252 | if (err) |
1253 | - goto out_err; |
1254 | + goto out_unlock; |
1255 | s->s_dirt = 0; |
1256 | |
1257 | if (!(*mount_flags & MS_RDONLY)) { |
1258 | + /* |
1259 | + * Drop write lock. Quota will retake it when needed and lock |
1260 | + * ordering requires calling dquot_resume() without it. |
1261 | + */ |
1262 | + reiserfs_write_unlock(s); |
1263 | dquot_resume(s, -1); |
1264 | + reiserfs_write_lock(s); |
1265 | finish_unfinished(s); |
1266 | reiserfs_xattr_init(s, *mount_flags); |
1267 | } |
1268 | @@ -1413,9 +1427,10 @@ out_ok: |
1269 | reiserfs_write_unlock(s); |
1270 | return 0; |
1271 | |
1272 | +out_unlock: |
1273 | + reiserfs_write_unlock(s); |
1274 | out_err: |
1275 | kfree(new_opts); |
1276 | - reiserfs_write_unlock(s); |
1277 | return err; |
1278 | } |
1279 | |
1280 | @@ -2049,13 +2064,15 @@ static int reiserfs_write_dquot(struct dquot *dquot) |
1281 | REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); |
1282 | if (ret) |
1283 | goto out; |
1284 | + reiserfs_write_unlock(dquot->dq_sb); |
1285 | ret = dquot_commit(dquot); |
1286 | + reiserfs_write_lock(dquot->dq_sb); |
1287 | err = |
1288 | journal_end(&th, dquot->dq_sb, |
1289 | REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); |
1290 | if (!ret && err) |
1291 | ret = err; |
1292 | - out: |
1293 | +out: |
1294 | reiserfs_write_unlock(dquot->dq_sb); |
1295 | return ret; |
1296 | } |
1297 | @@ -2071,13 +2088,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) |
1298 | REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); |
1299 | if (ret) |
1300 | goto out; |
1301 | + reiserfs_write_unlock(dquot->dq_sb); |
1302 | ret = dquot_acquire(dquot); |
1303 | + reiserfs_write_lock(dquot->dq_sb); |
1304 | err = |
1305 | journal_end(&th, dquot->dq_sb, |
1306 | REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); |
1307 | if (!ret && err) |
1308 | ret = err; |
1309 | - out: |
1310 | +out: |
1311 | reiserfs_write_unlock(dquot->dq_sb); |
1312 | return ret; |
1313 | } |
1314 | @@ -2091,19 +2110,21 @@ static int reiserfs_release_dquot(struct dquot *dquot) |
1315 | ret = |
1316 | journal_begin(&th, dquot->dq_sb, |
1317 | REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); |
1318 | + reiserfs_write_unlock(dquot->dq_sb); |
1319 | if (ret) { |
1320 | /* Release dquot anyway to avoid endless cycle in dqput() */ |
1321 | dquot_release(dquot); |
1322 | goto out; |
1323 | } |
1324 | ret = dquot_release(dquot); |
1325 | + reiserfs_write_lock(dquot->dq_sb); |
1326 | err = |
1327 | journal_end(&th, dquot->dq_sb, |
1328 | REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); |
1329 | if (!ret && err) |
1330 | ret = err; |
1331 | - out: |
1332 | reiserfs_write_unlock(dquot->dq_sb); |
1333 | +out: |
1334 | return ret; |
1335 | } |
1336 | |
1337 | @@ -2128,11 +2149,13 @@ static int reiserfs_write_info(struct super_block *sb, int type) |
1338 | ret = journal_begin(&th, sb, 2); |
1339 | if (ret) |
1340 | goto out; |
1341 | + reiserfs_write_unlock(sb); |
1342 | ret = dquot_commit_info(sb, type); |
1343 | + reiserfs_write_lock(sb); |
1344 | err = journal_end(&th, sb, 2); |
1345 | if (!ret && err) |
1346 | ret = err; |
1347 | - out: |
1348 | +out: |
1349 | reiserfs_write_unlock(sb); |
1350 | return ret; |
1351 | } |
1352 | @@ -2157,8 +2180,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, |
1353 | struct reiserfs_transaction_handle th; |
1354 | int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; |
1355 | |
1356 | - if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) |
1357 | - return -EINVAL; |
1358 | + reiserfs_write_lock(sb); |
1359 | + if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { |
1360 | + err = -EINVAL; |
1361 | + goto out; |
1362 | + } |
1363 | |
1364 | /* Quotafile not on the same filesystem? */ |
1365 | if (path->dentry->d_sb != sb) { |
1366 | @@ -2200,8 +2226,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, |
1367 | if (err) |
1368 | goto out; |
1369 | } |
1370 | - err = dquot_quota_on(sb, type, format_id, path); |
1371 | + reiserfs_write_unlock(sb); |
1372 | + return dquot_quota_on(sb, type, format_id, path); |
1373 | out: |
1374 | + reiserfs_write_unlock(sb); |
1375 | return err; |
1376 | } |
1377 | |
1378 | @@ -2275,7 +2303,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, |
1379 | tocopy = sb->s_blocksize - offset < towrite ? |
1380 | sb->s_blocksize - offset : towrite; |
1381 | tmp_bh.b_state = 0; |
1382 | + reiserfs_write_lock(sb); |
1383 | err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); |
1384 | + reiserfs_write_unlock(sb); |
1385 | if (err) |
1386 | goto out; |
1387 | if (offset || tocopy != sb->s_blocksize) |
1388 | @@ -2291,10 +2321,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, |
1389 | flush_dcache_page(bh->b_page); |
1390 | set_buffer_uptodate(bh); |
1391 | unlock_buffer(bh); |
1392 | + reiserfs_write_lock(sb); |
1393 | reiserfs_prepare_for_journal(sb, bh, 1); |
1394 | journal_mark_dirty(current->journal_info, sb, bh); |
1395 | if (!journal_quota) |
1396 | reiserfs_add_ordered_list(inode, bh); |
1397 | + reiserfs_write_unlock(sb); |
1398 | brelse(bh); |
1399 | offset = 0; |
1400 | towrite -= tocopy; |
1401 | diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c |
1402 | index 2559d17..5dc48ca 100644 |
1403 | --- a/fs/ubifs/find.c |
1404 | +++ b/fs/ubifs/find.c |
1405 | @@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c) |
1406 | if (!lprops) { |
1407 | lprops = ubifs_fast_find_freeable(c); |
1408 | if (!lprops) { |
1409 | - ubifs_assert(c->freeable_cnt == 0); |
1410 | - if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { |
1411 | + /* |
1412 | + * The first condition means the following: go scan the |
1413 | + * LPT if there are uncategorized lprops, which means |
1414 | + * there may be freeable LEBs there (UBIFS does not |
1415 | + * store the information about freeable LEBs in the |
1416 | + * master node). |
1417 | + */ |
1418 | + if (c->in_a_category_cnt != c->main_lebs || |
1419 | + c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { |
1420 | + ubifs_assert(c->freeable_cnt == 0); |
1421 | lprops = scan_for_leb_for_idx(c); |
1422 | if (IS_ERR(lprops)) { |
1423 | err = PTR_ERR(lprops); |
1424 | diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c |
1425 | index f8a181e..ea9d491 100644 |
1426 | --- a/fs/ubifs/lprops.c |
1427 | +++ b/fs/ubifs/lprops.c |
1428 | @@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, |
1429 | default: |
1430 | ubifs_assert(0); |
1431 | } |
1432 | + |
1433 | lprops->flags &= ~LPROPS_CAT_MASK; |
1434 | lprops->flags |= cat; |
1435 | + c->in_a_category_cnt += 1; |
1436 | + ubifs_assert(c->in_a_category_cnt <= c->main_lebs); |
1437 | } |
1438 | |
1439 | /** |
1440 | @@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c, |
1441 | default: |
1442 | ubifs_assert(0); |
1443 | } |
1444 | + |
1445 | + c->in_a_category_cnt -= 1; |
1446 | + ubifs_assert(c->in_a_category_cnt >= 0); |
1447 | } |
1448 | |
1449 | /** |
1450 | diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h |
1451 | index 93d59ac..4971cb2 100644 |
1452 | --- a/fs/ubifs/ubifs.h |
1453 | +++ b/fs/ubifs/ubifs.h |
1454 | @@ -1184,6 +1184,8 @@ struct ubifs_debug_info; |
1455 | * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size) |
1456 | * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size) |
1457 | * @freeable_cnt: number of freeable LEBs in @freeable_list |
1458 | + * @in_a_category_cnt: count of lprops which are in a certain category, which |
1459 | + * basically meants that they were loaded from the flash |
1460 | * |
1461 | * @ltab_lnum: LEB number of LPT's own lprops table |
1462 | * @ltab_offs: offset of LPT's own lprops table |
1463 | @@ -1413,6 +1415,7 @@ struct ubifs_info { |
1464 | struct list_head freeable_list; |
1465 | struct list_head frdi_idx_list; |
1466 | int freeable_cnt; |
1467 | + int in_a_category_cnt; |
1468 | |
1469 | int ltab_lnum; |
1470 | int ltab_offs; |
1471 | diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c |
1472 | index 6819b51..bb76128 100644 |
1473 | --- a/fs/xfs/xfs_buf.c |
1474 | +++ b/fs/xfs/xfs_buf.c |
1475 | @@ -1165,9 +1165,14 @@ xfs_buf_bio_end_io( |
1476 | { |
1477 | xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; |
1478 | |
1479 | - xfs_buf_ioerror(bp, -error); |
1480 | + /* |
1481 | + * don't overwrite existing errors - otherwise we can lose errors on |
1482 | + * buffers that require multiple bios to complete. |
1483 | + */ |
1484 | + if (!bp->b_error) |
1485 | + xfs_buf_ioerror(bp, -error); |
1486 | |
1487 | - if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) |
1488 | + if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) |
1489 | invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); |
1490 | |
1491 | _xfs_buf_ioend(bp, 1); |
1492 | @@ -1243,6 +1248,11 @@ next_chunk: |
1493 | if (size) |
1494 | goto next_chunk; |
1495 | } else { |
1496 | + /* |
1497 | + * This is guaranteed not to be the last io reference count |
1498 | + * because the caller (xfs_buf_iorequest) holds a count itself. |
1499 | + */ |
1500 | + atomic_dec(&bp->b_io_remaining); |
1501 | xfs_buf_ioerror(bp, EIO); |
1502 | bio_put(bio); |
1503 | } |
1504 | diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h |
1505 | index aa13392..d4080f3 100644 |
1506 | --- a/include/linux/ceph/auth.h |
1507 | +++ b/include/linux/ceph/auth.h |
1508 | @@ -14,6 +14,14 @@ |
1509 | struct ceph_auth_client; |
1510 | struct ceph_authorizer; |
1511 | |
1512 | +struct ceph_auth_handshake { |
1513 | + struct ceph_authorizer *authorizer; |
1514 | + void *authorizer_buf; |
1515 | + size_t authorizer_buf_len; |
1516 | + void *authorizer_reply_buf; |
1517 | + size_t authorizer_reply_buf_len; |
1518 | +}; |
1519 | + |
1520 | struct ceph_auth_client_ops { |
1521 | const char *name; |
1522 | |
1523 | @@ -43,9 +51,7 @@ struct ceph_auth_client_ops { |
1524 | * the response to authenticate the service. |
1525 | */ |
1526 | int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type, |
1527 | - struct ceph_authorizer **a, |
1528 | - void **buf, size_t *len, |
1529 | - void **reply_buf, size_t *reply_len); |
1530 | + struct ceph_auth_handshake *auth); |
1531 | int (*verify_authorizer_reply)(struct ceph_auth_client *ac, |
1532 | struct ceph_authorizer *a, size_t len); |
1533 | void (*destroy_authorizer)(struct ceph_auth_client *ac, |
1534 | diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h |
1535 | index e71d683..98ec36a 100644 |
1536 | --- a/include/linux/ceph/libceph.h |
1537 | +++ b/include/linux/ceph/libceph.h |
1538 | @@ -132,7 +132,7 @@ struct ceph_client { |
1539 | u32 supported_features; |
1540 | u32 required_features; |
1541 | |
1542 | - struct ceph_messenger *msgr; /* messenger instance */ |
1543 | + struct ceph_messenger msgr; /* messenger instance */ |
1544 | struct ceph_mon_client monc; |
1545 | struct ceph_osd_client osdc; |
1546 | |
1547 | diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h |
1548 | index 3bff047..189ae06 100644 |
1549 | --- a/include/linux/ceph/messenger.h |
1550 | +++ b/include/linux/ceph/messenger.h |
1551 | @@ -25,15 +25,12 @@ struct ceph_connection_operations { |
1552 | void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m); |
1553 | |
1554 | /* authorize an outgoing connection */ |
1555 | - int (*get_authorizer) (struct ceph_connection *con, |
1556 | - void **buf, int *len, int *proto, |
1557 | - void **reply_buf, int *reply_len, int force_new); |
1558 | + struct ceph_auth_handshake *(*get_authorizer) ( |
1559 | + struct ceph_connection *con, |
1560 | + int *proto, int force_new); |
1561 | int (*verify_authorizer_reply) (struct ceph_connection *con, int len); |
1562 | int (*invalidate_authorizer)(struct ceph_connection *con); |
1563 | |
1564 | - /* protocol version mismatch */ |
1565 | - void (*bad_proto) (struct ceph_connection *con); |
1566 | - |
1567 | /* there was some error on the socket (disconnect, whatever) */ |
1568 | void (*fault) (struct ceph_connection *con); |
1569 | |
1570 | @@ -53,6 +50,7 @@ struct ceph_messenger { |
1571 | struct ceph_entity_inst inst; /* my name+address */ |
1572 | struct ceph_entity_addr my_enc_addr; |
1573 | |
1574 | + atomic_t stopping; |
1575 | bool nocrc; |
1576 | |
1577 | /* |
1578 | @@ -80,7 +78,10 @@ struct ceph_msg { |
1579 | unsigned nr_pages; /* size of page array */ |
1580 | unsigned page_alignment; /* io offset in first page */ |
1581 | struct ceph_pagelist *pagelist; /* instead of pages */ |
1582 | + |
1583 | + struct ceph_connection *con; |
1584 | struct list_head list_head; |
1585 | + |
1586 | struct kref kref; |
1587 | struct bio *bio; /* instead of pages/pagelist */ |
1588 | struct bio *bio_iter; /* bio iterator */ |
1589 | @@ -106,23 +107,6 @@ struct ceph_msg_pos { |
1590 | #define MAX_DELAY_INTERVAL (5 * 60 * HZ) |
1591 | |
1592 | /* |
1593 | - * ceph_connection state bit flags |
1594 | - */ |
1595 | -#define LOSSYTX 0 /* we can close channel or drop messages on errors */ |
1596 | -#define CONNECTING 1 |
1597 | -#define NEGOTIATING 2 |
1598 | -#define KEEPALIVE_PENDING 3 |
1599 | -#define WRITE_PENDING 4 /* we have data ready to send */ |
1600 | -#define STANDBY 8 /* no outgoing messages, socket closed. we keep |
1601 | - * the ceph_connection around to maintain shared |
1602 | - * state with the peer. */ |
1603 | -#define CLOSED 10 /* we've closed the connection */ |
1604 | -#define SOCK_CLOSED 11 /* socket state changed to closed */ |
1605 | -#define OPENING 13 /* open connection w/ (possibly new) peer */ |
1606 | -#define DEAD 14 /* dead, about to kfree */ |
1607 | -#define BACKOFF 15 |
1608 | - |
1609 | -/* |
1610 | * A single connection with another host. |
1611 | * |
1612 | * We maintain a queue of outgoing messages, and some session state to |
1613 | @@ -131,18 +115,22 @@ struct ceph_msg_pos { |
1614 | */ |
1615 | struct ceph_connection { |
1616 | void *private; |
1617 | - atomic_t nref; |
1618 | |
1619 | const struct ceph_connection_operations *ops; |
1620 | |
1621 | struct ceph_messenger *msgr; |
1622 | + |
1623 | + atomic_t sock_state; |
1624 | struct socket *sock; |
1625 | - unsigned long state; /* connection state (see flags above) */ |
1626 | + struct ceph_entity_addr peer_addr; /* peer address */ |
1627 | + struct ceph_entity_addr peer_addr_for_me; |
1628 | + |
1629 | + unsigned long flags; |
1630 | + unsigned long state; |
1631 | const char *error_msg; /* error message, if any */ |
1632 | |
1633 | - struct ceph_entity_addr peer_addr; /* peer address */ |
1634 | struct ceph_entity_name peer_name; /* peer name */ |
1635 | - struct ceph_entity_addr peer_addr_for_me; |
1636 | + |
1637 | unsigned peer_features; |
1638 | u32 connect_seq; /* identify the most recent connection |
1639 | attempt for this connection, client */ |
1640 | @@ -163,16 +151,8 @@ struct ceph_connection { |
1641 | |
1642 | /* connection negotiation temps */ |
1643 | char in_banner[CEPH_BANNER_MAX_LEN]; |
1644 | - union { |
1645 | - struct { /* outgoing connection */ |
1646 | - struct ceph_msg_connect out_connect; |
1647 | - struct ceph_msg_connect_reply in_reply; |
1648 | - }; |
1649 | - struct { /* incoming */ |
1650 | - struct ceph_msg_connect in_connect; |
1651 | - struct ceph_msg_connect_reply out_reply; |
1652 | - }; |
1653 | - }; |
1654 | + struct ceph_msg_connect out_connect; |
1655 | + struct ceph_msg_connect_reply in_reply; |
1656 | struct ceph_entity_addr actual_peer_addr; |
1657 | |
1658 | /* message out temps */ |
1659 | @@ -215,24 +195,26 @@ extern int ceph_msgr_init(void); |
1660 | extern void ceph_msgr_exit(void); |
1661 | extern void ceph_msgr_flush(void); |
1662 | |
1663 | -extern struct ceph_messenger *ceph_messenger_create( |
1664 | - struct ceph_entity_addr *myaddr, |
1665 | - u32 features, u32 required); |
1666 | -extern void ceph_messenger_destroy(struct ceph_messenger *); |
1667 | +extern void ceph_messenger_init(struct ceph_messenger *msgr, |
1668 | + struct ceph_entity_addr *myaddr, |
1669 | + u32 supported_features, |
1670 | + u32 required_features, |
1671 | + bool nocrc); |
1672 | |
1673 | -extern void ceph_con_init(struct ceph_messenger *msgr, |
1674 | - struct ceph_connection *con); |
1675 | +extern void ceph_con_init(struct ceph_connection *con, void *private, |
1676 | + const struct ceph_connection_operations *ops, |
1677 | + struct ceph_messenger *msgr); |
1678 | extern void ceph_con_open(struct ceph_connection *con, |
1679 | + __u8 entity_type, __u64 entity_num, |
1680 | struct ceph_entity_addr *addr); |
1681 | extern bool ceph_con_opened(struct ceph_connection *con); |
1682 | extern void ceph_con_close(struct ceph_connection *con); |
1683 | extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg); |
1684 | -extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg); |
1685 | -extern void ceph_con_revoke_message(struct ceph_connection *con, |
1686 | - struct ceph_msg *msg); |
1687 | + |
1688 | +extern void ceph_msg_revoke(struct ceph_msg *msg); |
1689 | +extern void ceph_msg_revoke_incoming(struct ceph_msg *msg); |
1690 | + |
1691 | extern void ceph_con_keepalive(struct ceph_connection *con); |
1692 | -extern struct ceph_connection *ceph_con_get(struct ceph_connection *con); |
1693 | -extern void ceph_con_put(struct ceph_connection *con); |
1694 | |
1695 | extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, |
1696 | bool can_fail); |
1697 | diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h |
1698 | index 545f859..2113e38 100644 |
1699 | --- a/include/linux/ceph/mon_client.h |
1700 | +++ b/include/linux/ceph/mon_client.h |
1701 | @@ -70,7 +70,7 @@ struct ceph_mon_client { |
1702 | bool hunting; |
1703 | int cur_mon; /* last monitor i contacted */ |
1704 | unsigned long sub_sent, sub_renew_after; |
1705 | - struct ceph_connection *con; |
1706 | + struct ceph_connection con; |
1707 | bool have_fsid; |
1708 | |
1709 | /* pending generic requests */ |
1710 | diff --git a/include/linux/ceph/msgpool.h b/include/linux/ceph/msgpool.h |
1711 | index a362605..09fa96b 100644 |
1712 | --- a/include/linux/ceph/msgpool.h |
1713 | +++ b/include/linux/ceph/msgpool.h |
1714 | @@ -11,10 +11,11 @@ |
1715 | struct ceph_msgpool { |
1716 | const char *name; |
1717 | mempool_t *pool; |
1718 | + int type; /* preallocated message type */ |
1719 | int front_len; /* preallocated payload size */ |
1720 | }; |
1721 | |
1722 | -extern int ceph_msgpool_init(struct ceph_msgpool *pool, |
1723 | +extern int ceph_msgpool_init(struct ceph_msgpool *pool, int type, |
1724 | int front_len, int size, bool blocking, |
1725 | const char *name); |
1726 | extern void ceph_msgpool_destroy(struct ceph_msgpool *pool); |
1727 | diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h |
1728 | index 7c05ac2..d9b880e 100644 |
1729 | --- a/include/linux/ceph/osd_client.h |
1730 | +++ b/include/linux/ceph/osd_client.h |
1731 | @@ -6,9 +6,10 @@ |
1732 | #include <linux/mempool.h> |
1733 | #include <linux/rbtree.h> |
1734 | |
1735 | -#include "types.h" |
1736 | -#include "osdmap.h" |
1737 | -#include "messenger.h" |
1738 | +#include <linux/ceph/types.h> |
1739 | +#include <linux/ceph/osdmap.h> |
1740 | +#include <linux/ceph/messenger.h> |
1741 | +#include <linux/ceph/auth.h> |
1742 | |
1743 | /* |
1744 | * Maximum object name size |
1745 | @@ -40,9 +41,7 @@ struct ceph_osd { |
1746 | struct list_head o_requests; |
1747 | struct list_head o_linger_requests; |
1748 | struct list_head o_osd_lru; |
1749 | - struct ceph_authorizer *o_authorizer; |
1750 | - void *o_authorizer_buf, *o_authorizer_reply_buf; |
1751 | - size_t o_authorizer_buf_len, o_authorizer_reply_buf_len; |
1752 | + struct ceph_auth_handshake o_auth; |
1753 | unsigned long lru_ttl; |
1754 | int o_marked_for_keepalive; |
1755 | struct list_head o_keepalive_item; |
1756 | @@ -208,7 +207,7 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, |
1757 | extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, |
1758 | struct ceph_msg *msg); |
1759 | |
1760 | -extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
1761 | +extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
1762 | struct ceph_file_layout *layout, |
1763 | u64 snapid, |
1764 | u64 off, u64 *plen, u64 *bno, |
1765 | diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h |
1766 | index ba4c205..11db454 100644 |
1767 | --- a/include/linux/ceph/osdmap.h |
1768 | +++ b/include/linux/ceph/osdmap.h |
1769 | @@ -111,9 +111,9 @@ extern struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, |
1770 | extern void ceph_osdmap_destroy(struct ceph_osdmap *map); |
1771 | |
1772 | /* calculate mapping of a file extent to an object */ |
1773 | -extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
1774 | - u64 off, u64 *plen, |
1775 | - u64 *bno, u64 *oxoff, u64 *oxlen); |
1776 | +extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
1777 | + u64 off, u64 *plen, |
1778 | + u64 *bno, u64 *oxoff, u64 *oxlen); |
1779 | |
1780 | /* calculate mapping of object to a placement group */ |
1781 | extern int ceph_calc_object_layout(struct ceph_object_layout *ol, |
1782 | diff --git a/include/linux/crush/crush.h b/include/linux/crush/crush.h |
1783 | index 97e435b..e7a8c90 100644 |
1784 | --- a/include/linux/crush/crush.h |
1785 | +++ b/include/linux/crush/crush.h |
1786 | @@ -168,7 +168,7 @@ struct crush_map { |
1787 | |
1788 | |
1789 | /* crush.c */ |
1790 | -extern int crush_get_bucket_item_weight(struct crush_bucket *b, int pos); |
1791 | +extern int crush_get_bucket_item_weight(const struct crush_bucket *b, int pos); |
1792 | extern void crush_calc_parents(struct crush_map *map); |
1793 | extern void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b); |
1794 | extern void crush_destroy_bucket_list(struct crush_bucket_list *b); |
1795 | @@ -177,4 +177,9 @@ extern void crush_destroy_bucket_straw(struct crush_bucket_straw *b); |
1796 | extern void crush_destroy_bucket(struct crush_bucket *b); |
1797 | extern void crush_destroy(struct crush_map *map); |
1798 | |
1799 | +static inline int crush_calc_tree_node(int i) |
1800 | +{ |
1801 | + return ((i+1) << 1)-1; |
1802 | +} |
1803 | + |
1804 | #endif |
1805 | diff --git a/include/linux/crush/mapper.h b/include/linux/crush/mapper.h |
1806 | index c46b99c..9322ab8 100644 |
1807 | --- a/include/linux/crush/mapper.h |
1808 | +++ b/include/linux/crush/mapper.h |
1809 | @@ -10,11 +10,11 @@ |
1810 | |
1811 | #include "crush.h" |
1812 | |
1813 | -extern int crush_find_rule(struct crush_map *map, int pool, int type, int size); |
1814 | -extern int crush_do_rule(struct crush_map *map, |
1815 | +extern int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size); |
1816 | +extern int crush_do_rule(const struct crush_map *map, |
1817 | int ruleno, |
1818 | int x, int *result, int result_max, |
1819 | int forcefeed, /* -1 for none */ |
1820 | - __u32 *weights); |
1821 | + const __u32 *weights); |
1822 | |
1823 | #endif |
1824 | diff --git a/kernel/module.c b/kernel/module.c |
1825 | index 61ea75e..8597217 100644 |
1826 | --- a/kernel/module.c |
1827 | +++ b/kernel/module.c |
1828 | @@ -2273,12 +2273,17 @@ static void layout_symtab(struct module *mod, struct load_info *info) |
1829 | src = (void *)info->hdr + symsect->sh_offset; |
1830 | nsrc = symsect->sh_size / sizeof(*src); |
1831 | |
1832 | + /* strtab always starts with a nul, so offset 0 is the empty string. */ |
1833 | + strtab_size = 1; |
1834 | + |
1835 | /* Compute total space required for the core symbols' strtab. */ |
1836 | - for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) |
1837 | - if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { |
1838 | - strtab_size += strlen(&info->strtab[src->st_name]) + 1; |
1839 | + for (ndst = i = 0; i < nsrc; i++) { |
1840 | + if (i == 0 || |
1841 | + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { |
1842 | + strtab_size += strlen(&info->strtab[src[i].st_name])+1; |
1843 | ndst++; |
1844 | } |
1845 | + } |
1846 | |
1847 | /* Append room for core symbols at end of core part. */ |
1848 | info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); |
1849 | @@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) |
1850 | mod->core_symtab = dst = mod->module_core + info->symoffs; |
1851 | mod->core_strtab = s = mod->module_core + info->stroffs; |
1852 | src = mod->symtab; |
1853 | - *dst = *src; |
1854 | *s++ = 0; |
1855 | - for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { |
1856 | - if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) |
1857 | - continue; |
1858 | - |
1859 | - dst[ndst] = *src; |
1860 | - dst[ndst++].st_name = s - mod->core_strtab; |
1861 | - s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; |
1862 | + for (ndst = i = 0; i < mod->num_symtab; i++) { |
1863 | + if (i == 0 || |
1864 | + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { |
1865 | + dst[ndst] = src[i]; |
1866 | + dst[ndst++].st_name = s - mod->core_strtab; |
1867 | + s += strlcpy(s, &mod->strtab[src[i].st_name], |
1868 | + KSYM_NAME_LEN) + 1; |
1869 | + } |
1870 | } |
1871 | mod->core_num_syms = ndst; |
1872 | } |
1873 | diff --git a/mm/memcontrol.c b/mm/memcontrol.c |
1874 | index 7685d4a..81c275b 100644 |
1875 | --- a/mm/memcontrol.c |
1876 | +++ b/mm/memcontrol.c |
1877 | @@ -1489,17 +1489,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg) |
1878 | u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) |
1879 | { |
1880 | u64 limit; |
1881 | - u64 memsw; |
1882 | |
1883 | limit = res_counter_read_u64(&memcg->res, RES_LIMIT); |
1884 | - limit += total_swap_pages << PAGE_SHIFT; |
1885 | |
1886 | - memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); |
1887 | /* |
1888 | - * If memsw is finite and limits the amount of swap space available |
1889 | - * to this memcg, return that limit. |
1890 | + * Do not consider swap space if we cannot swap due to swappiness |
1891 | */ |
1892 | - return min(limit, memsw); |
1893 | + if (mem_cgroup_swappiness(memcg)) { |
1894 | + u64 memsw; |
1895 | + |
1896 | + limit += total_swap_pages << PAGE_SHIFT; |
1897 | + memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); |
1898 | + |
1899 | + /* |
1900 | + * If memsw is finite and limits the amount of swap space |
1901 | + * available to this memcg, return that limit. |
1902 | + */ |
1903 | + limit = min(limit, memsw); |
1904 | + } |
1905 | + |
1906 | + return limit; |
1907 | } |
1908 | |
1909 | static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg, |
1910 | diff --git a/mm/shmem.c b/mm/shmem.c |
1911 | index 40383cd..a859b06 100644 |
1912 | --- a/mm/shmem.c |
1913 | +++ b/mm/shmem.c |
1914 | @@ -595,7 +595,7 @@ static void shmem_evict_inode(struct inode *inode) |
1915 | kfree(xattr->name); |
1916 | kfree(xattr); |
1917 | } |
1918 | - BUG_ON(inode->i_blocks); |
1919 | + WARN_ON(inode->i_blocks); |
1920 | shmem_free_inode(inode->i_sb); |
1921 | end_writeback(inode); |
1922 | } |
1923 | diff --git a/mm/vmscan.c b/mm/vmscan.c |
1924 | index e989ee2..e6ca505 100644 |
1925 | --- a/mm/vmscan.c |
1926 | +++ b/mm/vmscan.c |
1927 | @@ -3128,6 +3128,8 @@ static int kswapd(void *p) |
1928 | &balanced_classzone_idx); |
1929 | } |
1930 | } |
1931 | + |
1932 | + current->reclaim_state = NULL; |
1933 | return 0; |
1934 | } |
1935 | |
1936 | diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c |
1937 | index 214c2bb..925ca58 100644 |
1938 | --- a/net/ceph/auth_none.c |
1939 | +++ b/net/ceph/auth_none.c |
1940 | @@ -59,9 +59,7 @@ static int handle_reply(struct ceph_auth_client *ac, int result, |
1941 | */ |
1942 | static int ceph_auth_none_create_authorizer( |
1943 | struct ceph_auth_client *ac, int peer_type, |
1944 | - struct ceph_authorizer **a, |
1945 | - void **buf, size_t *len, |
1946 | - void **reply_buf, size_t *reply_len) |
1947 | + struct ceph_auth_handshake *auth) |
1948 | { |
1949 | struct ceph_auth_none_info *ai = ac->private; |
1950 | struct ceph_none_authorizer *au = &ai->au; |
1951 | @@ -82,11 +80,12 @@ static int ceph_auth_none_create_authorizer( |
1952 | dout("built authorizer len %d\n", au->buf_len); |
1953 | } |
1954 | |
1955 | - *a = (struct ceph_authorizer *)au; |
1956 | - *buf = au->buf; |
1957 | - *len = au->buf_len; |
1958 | - *reply_buf = au->reply_buf; |
1959 | - *reply_len = sizeof(au->reply_buf); |
1960 | + auth->authorizer = (struct ceph_authorizer *) au; |
1961 | + auth->authorizer_buf = au->buf; |
1962 | + auth->authorizer_buf_len = au->buf_len; |
1963 | + auth->authorizer_reply_buf = au->reply_buf; |
1964 | + auth->authorizer_reply_buf_len = sizeof (au->reply_buf); |
1965 | + |
1966 | return 0; |
1967 | |
1968 | bad2: |
1969 | diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c |
1970 | index 1587dc6..a16bf14 100644 |
1971 | --- a/net/ceph/auth_x.c |
1972 | +++ b/net/ceph/auth_x.c |
1973 | @@ -526,9 +526,7 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result, |
1974 | |
1975 | static int ceph_x_create_authorizer( |
1976 | struct ceph_auth_client *ac, int peer_type, |
1977 | - struct ceph_authorizer **a, |
1978 | - void **buf, size_t *len, |
1979 | - void **reply_buf, size_t *reply_len) |
1980 | + struct ceph_auth_handshake *auth) |
1981 | { |
1982 | struct ceph_x_authorizer *au; |
1983 | struct ceph_x_ticket_handler *th; |
1984 | @@ -548,11 +546,12 @@ static int ceph_x_create_authorizer( |
1985 | return ret; |
1986 | } |
1987 | |
1988 | - *a = (struct ceph_authorizer *)au; |
1989 | - *buf = au->buf->vec.iov_base; |
1990 | - *len = au->buf->vec.iov_len; |
1991 | - *reply_buf = au->reply_buf; |
1992 | - *reply_len = sizeof(au->reply_buf); |
1993 | + auth->authorizer = (struct ceph_authorizer *) au; |
1994 | + auth->authorizer_buf = au->buf->vec.iov_base; |
1995 | + auth->authorizer_buf_len = au->buf->vec.iov_len; |
1996 | + auth->authorizer_reply_buf = au->reply_buf; |
1997 | + auth->authorizer_reply_buf_len = sizeof (au->reply_buf); |
1998 | + |
1999 | return 0; |
2000 | } |
2001 | |
2002 | diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c |
2003 | index cc91319..8e74e8c 100644 |
2004 | --- a/net/ceph/ceph_common.c |
2005 | +++ b/net/ceph/ceph_common.c |
2006 | @@ -83,7 +83,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) |
2007 | return -1; |
2008 | } |
2009 | } else { |
2010 | - pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); |
2011 | memcpy(&client->fsid, fsid, sizeof(*fsid)); |
2012 | } |
2013 | return 0; |
2014 | @@ -468,19 +467,15 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, |
2015 | /* msgr */ |
2016 | if (ceph_test_opt(client, MYIP)) |
2017 | myaddr = &client->options->my_addr; |
2018 | - client->msgr = ceph_messenger_create(myaddr, |
2019 | - client->supported_features, |
2020 | - client->required_features); |
2021 | - if (IS_ERR(client->msgr)) { |
2022 | - err = PTR_ERR(client->msgr); |
2023 | - goto fail; |
2024 | - } |
2025 | - client->msgr->nocrc = ceph_test_opt(client, NOCRC); |
2026 | + ceph_messenger_init(&client->msgr, myaddr, |
2027 | + client->supported_features, |
2028 | + client->required_features, |
2029 | + ceph_test_opt(client, NOCRC)); |
2030 | |
2031 | /* subsystems */ |
2032 | err = ceph_monc_init(&client->monc, client); |
2033 | if (err < 0) |
2034 | - goto fail_msgr; |
2035 | + goto fail; |
2036 | err = ceph_osdc_init(&client->osdc, client); |
2037 | if (err < 0) |
2038 | goto fail_monc; |
2039 | @@ -489,8 +484,6 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, |
2040 | |
2041 | fail_monc: |
2042 | ceph_monc_stop(&client->monc); |
2043 | -fail_msgr: |
2044 | - ceph_messenger_destroy(client->msgr); |
2045 | fail: |
2046 | kfree(client); |
2047 | return ERR_PTR(err); |
2048 | @@ -501,22 +494,15 @@ void ceph_destroy_client(struct ceph_client *client) |
2049 | { |
2050 | dout("destroy_client %p\n", client); |
2051 | |
2052 | + atomic_set(&client->msgr.stopping, 1); |
2053 | + |
2054 | /* unmount */ |
2055 | ceph_osdc_stop(&client->osdc); |
2056 | |
2057 | - /* |
2058 | - * make sure osd connections close out before destroying the |
2059 | - * auth module, which is needed to free those connections' |
2060 | - * ceph_authorizers. |
2061 | - */ |
2062 | - ceph_msgr_flush(); |
2063 | - |
2064 | ceph_monc_stop(&client->monc); |
2065 | |
2066 | ceph_debugfs_client_cleanup(client); |
2067 | |
2068 | - ceph_messenger_destroy(client->msgr); |
2069 | - |
2070 | ceph_destroy_options(client->options); |
2071 | |
2072 | kfree(client); |
2073 | diff --git a/net/ceph/crush/crush.c b/net/ceph/crush/crush.c |
2074 | index d6ebb13..fbda052 100644 |
2075 | --- a/net/ceph/crush/crush.c |
2076 | +++ b/net/ceph/crush/crush.c |
2077 | @@ -26,9 +26,9 @@ const char *crush_bucket_alg_name(int alg) |
2078 | * @b: bucket pointer |
2079 | * @p: item index in bucket |
2080 | */ |
2081 | -int crush_get_bucket_item_weight(struct crush_bucket *b, int p) |
2082 | +int crush_get_bucket_item_weight(const struct crush_bucket *b, int p) |
2083 | { |
2084 | - if (p >= b->size) |
2085 | + if ((__u32)p >= b->size) |
2086 | return 0; |
2087 | |
2088 | switch (b->alg) { |
2089 | @@ -37,9 +37,7 @@ int crush_get_bucket_item_weight(struct crush_bucket *b, int p) |
2090 | case CRUSH_BUCKET_LIST: |
2091 | return ((struct crush_bucket_list *)b)->item_weights[p]; |
2092 | case CRUSH_BUCKET_TREE: |
2093 | - if (p & 1) |
2094 | - return ((struct crush_bucket_tree *)b)->node_weights[p]; |
2095 | - return 0; |
2096 | + return ((struct crush_bucket_tree *)b)->node_weights[crush_calc_tree_node(p)]; |
2097 | case CRUSH_BUCKET_STRAW: |
2098 | return ((struct crush_bucket_straw *)b)->item_weights[p]; |
2099 | } |
2100 | @@ -87,6 +85,8 @@ void crush_destroy_bucket_list(struct crush_bucket_list *b) |
2101 | |
2102 | void crush_destroy_bucket_tree(struct crush_bucket_tree *b) |
2103 | { |
2104 | + kfree(b->h.perm); |
2105 | + kfree(b->h.items); |
2106 | kfree(b->node_weights); |
2107 | kfree(b); |
2108 | } |
2109 | @@ -124,10 +124,9 @@ void crush_destroy_bucket(struct crush_bucket *b) |
2110 | */ |
2111 | void crush_destroy(struct crush_map *map) |
2112 | { |
2113 | - int b; |
2114 | - |
2115 | /* buckets */ |
2116 | if (map->buckets) { |
2117 | + __s32 b; |
2118 | for (b = 0; b < map->max_buckets; b++) { |
2119 | if (map->buckets[b] == NULL) |
2120 | continue; |
2121 | @@ -138,6 +137,7 @@ void crush_destroy(struct crush_map *map) |
2122 | |
2123 | /* rules */ |
2124 | if (map->rules) { |
2125 | + __u32 b; |
2126 | for (b = 0; b < map->max_rules; b++) |
2127 | kfree(map->rules[b]); |
2128 | kfree(map->rules); |
2129 | diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c |
2130 | index b79747c..00baad5 100644 |
2131 | --- a/net/ceph/crush/mapper.c |
2132 | +++ b/net/ceph/crush/mapper.c |
2133 | @@ -32,9 +32,9 @@ |
2134 | * @type: storage ruleset type (user defined) |
2135 | * @size: output set size |
2136 | */ |
2137 | -int crush_find_rule(struct crush_map *map, int ruleset, int type, int size) |
2138 | +int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size) |
2139 | { |
2140 | - int i; |
2141 | + __u32 i; |
2142 | |
2143 | for (i = 0; i < map->max_rules; i++) { |
2144 | if (map->rules[i] && |
2145 | @@ -72,7 +72,7 @@ static int bucket_perm_choose(struct crush_bucket *bucket, |
2146 | unsigned i, s; |
2147 | |
2148 | /* start a new permutation if @x has changed */ |
2149 | - if (bucket->perm_x != x || bucket->perm_n == 0) { |
2150 | + if (bucket->perm_x != (__u32)x || bucket->perm_n == 0) { |
2151 | dprintk("bucket %d new x=%d\n", bucket->id, x); |
2152 | bucket->perm_x = x; |
2153 | |
2154 | @@ -152,8 +152,8 @@ static int bucket_list_choose(struct crush_bucket_list *bucket, |
2155 | return bucket->h.items[i]; |
2156 | } |
2157 | |
2158 | - BUG_ON(1); |
2159 | - return 0; |
2160 | + dprintk("bad list sums for bucket %d\n", bucket->h.id); |
2161 | + return bucket->h.items[0]; |
2162 | } |
2163 | |
2164 | |
2165 | @@ -219,7 +219,7 @@ static int bucket_tree_choose(struct crush_bucket_tree *bucket, |
2166 | static int bucket_straw_choose(struct crush_bucket_straw *bucket, |
2167 | int x, int r) |
2168 | { |
2169 | - int i; |
2170 | + __u32 i; |
2171 | int high = 0; |
2172 | __u64 high_draw = 0; |
2173 | __u64 draw; |
2174 | @@ -239,6 +239,7 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket, |
2175 | static int crush_bucket_choose(struct crush_bucket *in, int x, int r) |
2176 | { |
2177 | dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r); |
2178 | + BUG_ON(in->size == 0); |
2179 | switch (in->alg) { |
2180 | case CRUSH_BUCKET_UNIFORM: |
2181 | return bucket_uniform_choose((struct crush_bucket_uniform *)in, |
2182 | @@ -253,7 +254,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) |
2183 | return bucket_straw_choose((struct crush_bucket_straw *)in, |
2184 | x, r); |
2185 | default: |
2186 | - BUG_ON(1); |
2187 | + dprintk("unknown bucket %d alg %d\n", in->id, in->alg); |
2188 | return in->items[0]; |
2189 | } |
2190 | } |
2191 | @@ -262,7 +263,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) |
2192 | * true if device is marked "out" (failed, fully offloaded) |
2193 | * of the cluster |
2194 | */ |
2195 | -static int is_out(struct crush_map *map, __u32 *weight, int item, int x) |
2196 | +static int is_out(const struct crush_map *map, const __u32 *weight, int item, int x) |
2197 | { |
2198 | if (weight[item] >= 0x10000) |
2199 | return 0; |
2200 | @@ -287,16 +288,16 @@ static int is_out(struct crush_map *map, __u32 *weight, int item, int x) |
2201 | * @recurse_to_leaf: true if we want one device under each item of given type |
2202 | * @out2: second output vector for leaf items (if @recurse_to_leaf) |
2203 | */ |
2204 | -static int crush_choose(struct crush_map *map, |
2205 | +static int crush_choose(const struct crush_map *map, |
2206 | struct crush_bucket *bucket, |
2207 | - __u32 *weight, |
2208 | + const __u32 *weight, |
2209 | int x, int numrep, int type, |
2210 | int *out, int outpos, |
2211 | int firstn, int recurse_to_leaf, |
2212 | int *out2) |
2213 | { |
2214 | int rep; |
2215 | - int ftotal, flocal; |
2216 | + unsigned int ftotal, flocal; |
2217 | int retry_descent, retry_bucket, skip_rep; |
2218 | struct crush_bucket *in = bucket; |
2219 | int r; |
2220 | @@ -304,7 +305,7 @@ static int crush_choose(struct crush_map *map, |
2221 | int item = 0; |
2222 | int itemtype; |
2223 | int collide, reject; |
2224 | - const int orig_tries = 5; /* attempts before we fall back to search */ |
2225 | + const unsigned int orig_tries = 5; /* attempts before we fall back to search */ |
2226 | |
2227 | dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", |
2228 | bucket->id, x, outpos, numrep); |
2229 | @@ -325,7 +326,7 @@ static int crush_choose(struct crush_map *map, |
2230 | r = rep; |
2231 | if (in->alg == CRUSH_BUCKET_UNIFORM) { |
2232 | /* be careful */ |
2233 | - if (firstn || numrep >= in->size) |
2234 | + if (firstn || (__u32)numrep >= in->size) |
2235 | /* r' = r + f_total */ |
2236 | r += ftotal; |
2237 | else if (in->size % numrep == 0) |
2238 | @@ -354,7 +355,11 @@ static int crush_choose(struct crush_map *map, |
2239 | item = bucket_perm_choose(in, x, r); |
2240 | else |
2241 | item = crush_bucket_choose(in, x, r); |
2242 | - BUG_ON(item >= map->max_devices); |
2243 | + if (item >= map->max_devices) { |
2244 | + dprintk(" bad item %d\n", item); |
2245 | + skip_rep = 1; |
2246 | + break; |
2247 | + } |
2248 | |
2249 | /* desired type? */ |
2250 | if (item < 0) |
2251 | @@ -365,8 +370,12 @@ static int crush_choose(struct crush_map *map, |
2252 | |
2253 | /* keep going? */ |
2254 | if (itemtype != type) { |
2255 | - BUG_ON(item >= 0 || |
2256 | - (-1-item) >= map->max_buckets); |
2257 | + if (item >= 0 || |
2258 | + (-1-item) >= map->max_buckets) { |
2259 | + dprintk(" bad item type %d\n", type); |
2260 | + skip_rep = 1; |
2261 | + break; |
2262 | + } |
2263 | in = map->buckets[-1-item]; |
2264 | retry_bucket = 1; |
2265 | continue; |
2266 | @@ -415,7 +424,7 @@ reject: |
2267 | if (collide && flocal < 3) |
2268 | /* retry locally a few times */ |
2269 | retry_bucket = 1; |
2270 | - else if (flocal < in->size + orig_tries) |
2271 | + else if (flocal <= in->size + orig_tries) |
2272 | /* exhaustive bucket search */ |
2273 | retry_bucket = 1; |
2274 | else if (ftotal < 20) |
2275 | @@ -425,7 +434,7 @@ reject: |
2276 | /* else give up */ |
2277 | skip_rep = 1; |
2278 | dprintk(" reject %d collide %d " |
2279 | - "ftotal %d flocal %d\n", |
2280 | + "ftotal %u flocal %u\n", |
2281 | reject, collide, ftotal, |
2282 | flocal); |
2283 | } |
2284 | @@ -456,9 +465,9 @@ reject: |
2285 | * @result_max: maximum result size |
2286 | * @force: force initial replica choice; -1 for none |
2287 | */ |
2288 | -int crush_do_rule(struct crush_map *map, |
2289 | +int crush_do_rule(const struct crush_map *map, |
2290 | int ruleno, int x, int *result, int result_max, |
2291 | - int force, __u32 *weight) |
2292 | + int force, const __u32 *weight) |
2293 | { |
2294 | int result_len; |
2295 | int force_context[CRUSH_MAX_DEPTH]; |
2296 | @@ -473,12 +482,15 @@ int crush_do_rule(struct crush_map *map, |
2297 | int osize; |
2298 | int *tmp; |
2299 | struct crush_rule *rule; |
2300 | - int step; |
2301 | + __u32 step; |
2302 | int i, j; |
2303 | int numrep; |
2304 | int firstn; |
2305 | |
2306 | - BUG_ON(ruleno >= map->max_rules); |
2307 | + if ((__u32)ruleno >= map->max_rules) { |
2308 | + dprintk(" bad ruleno %d\n", ruleno); |
2309 | + return 0; |
2310 | + } |
2311 | |
2312 | rule = map->rules[ruleno]; |
2313 | result_len = 0; |
2314 | @@ -488,7 +500,8 @@ int crush_do_rule(struct crush_map *map, |
2315 | /* |
2316 | * determine hierarchical context of force, if any. note |
2317 | * that this may or may not correspond to the specific types |
2318 | - * referenced by the crush rule. |
2319 | + * referenced by the crush rule. it will also only affect |
2320 | + * the first descent (TAKE). |
2321 | */ |
2322 | if (force >= 0 && |
2323 | force < map->max_devices && |
2324 | @@ -527,7 +540,8 @@ int crush_do_rule(struct crush_map *map, |
2325 | firstn = 1; |
2326 | case CRUSH_RULE_CHOOSE_LEAF_INDEP: |
2327 | case CRUSH_RULE_CHOOSE_INDEP: |
2328 | - BUG_ON(wsize == 0); |
2329 | + if (wsize == 0) |
2330 | + break; |
2331 | |
2332 | recurse_to_leaf = |
2333 | rule->steps[step].op == |
2334 | @@ -596,7 +610,9 @@ int crush_do_rule(struct crush_map *map, |
2335 | break; |
2336 | |
2337 | default: |
2338 | - BUG_ON(1); |
2339 | + dprintk(" unknown op %d at step %d\n", |
2340 | + curstep->op, step); |
2341 | + break; |
2342 | } |
2343 | } |
2344 | return result_len; |
2345 | diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c |
2346 | index b780cb7..9da7fdd 100644 |
2347 | --- a/net/ceph/crypto.c |
2348 | +++ b/net/ceph/crypto.c |
2349 | @@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) { |
2350 | struct ceph_crypto_key *ckey = key->payload.data; |
2351 | |
2352 | ceph_crypto_key_destroy(ckey); |
2353 | + kfree(ckey); |
2354 | } |
2355 | |
2356 | struct key_type key_type_ceph = { |
2357 | diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h |
2358 | index 1919d15..3572dc5 100644 |
2359 | --- a/net/ceph/crypto.h |
2360 | +++ b/net/ceph/crypto.h |
2361 | @@ -16,7 +16,8 @@ struct ceph_crypto_key { |
2362 | |
2363 | static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) |
2364 | { |
2365 | - kfree(key->key); |
2366 | + if (key) |
2367 | + kfree(key->key); |
2368 | } |
2369 | |
2370 | extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, |
2371 | diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c |
2372 | index 27d4ea3..680978d 100644 |
2373 | --- a/net/ceph/debugfs.c |
2374 | +++ b/net/ceph/debugfs.c |
2375 | @@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) |
2376 | snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, |
2377 | client->monc.auth->global_id); |
2378 | |
2379 | + dout("ceph_debugfs_client_init %p %s\n", client, name); |
2380 | + |
2381 | + BUG_ON(client->debugfs_dir); |
2382 | client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); |
2383 | if (!client->debugfs_dir) |
2384 | goto out; |
2385 | @@ -234,6 +237,7 @@ out: |
2386 | |
2387 | void ceph_debugfs_client_cleanup(struct ceph_client *client) |
2388 | { |
2389 | + dout("ceph_debugfs_client_cleanup %p\n", client); |
2390 | debugfs_remove(client->debugfs_osdmap); |
2391 | debugfs_remove(client->debugfs_monmap); |
2392 | debugfs_remove(client->osdc.debugfs_file); |
2393 | diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c |
2394 | index f0993af..aa71a67 100644 |
2395 | --- a/net/ceph/messenger.c |
2396 | +++ b/net/ceph/messenger.c |
2397 | @@ -29,6 +29,74 @@ |
2398 | * the sender. |
2399 | */ |
2400 | |
2401 | +/* |
2402 | + * We track the state of the socket on a given connection using |
2403 | + * values defined below. The transition to a new socket state is |
2404 | + * handled by a function which verifies we aren't coming from an |
2405 | + * unexpected state. |
2406 | + * |
2407 | + * -------- |
2408 | + * | NEW* | transient initial state |
2409 | + * -------- |
2410 | + * | con_sock_state_init() |
2411 | + * v |
2412 | + * ---------- |
2413 | + * | CLOSED | initialized, but no socket (and no |
2414 | + * ---------- TCP connection) |
2415 | + * ^ \ |
2416 | + * | \ con_sock_state_connecting() |
2417 | + * | ---------------------- |
2418 | + * | \ |
2419 | + * + con_sock_state_closed() \ |
2420 | + * |+--------------------------- \ |
2421 | + * | \ \ \ |
2422 | + * | ----------- \ \ |
2423 | + * | | CLOSING | socket event; \ \ |
2424 | + * | ----------- await close \ \ |
2425 | + * | ^ \ | |
2426 | + * | | \ | |
2427 | + * | + con_sock_state_closing() \ | |
2428 | + * | / \ | | |
2429 | + * | / --------------- | | |
2430 | + * | / \ v v |
2431 | + * | / -------------- |
2432 | + * | / -----------------| CONNECTING | socket created, TCP |
2433 | + * | | / -------------- connect initiated |
2434 | + * | | | con_sock_state_connected() |
2435 | + * | | v |
2436 | + * ------------- |
2437 | + * | CONNECTED | TCP connection established |
2438 | + * ------------- |
2439 | + * |
2440 | + * State values for ceph_connection->sock_state; NEW is assumed to be 0. |
2441 | + */ |
2442 | + |
2443 | +#define CON_SOCK_STATE_NEW 0 /* -> CLOSED */ |
2444 | +#define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */ |
2445 | +#define CON_SOCK_STATE_CONNECTING 2 /* -> CONNECTED or -> CLOSING */ |
2446 | +#define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */ |
2447 | +#define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */ |
2448 | + |
2449 | +/* |
2450 | + * connection states |
2451 | + */ |
2452 | +#define CON_STATE_CLOSED 1 /* -> PREOPEN */ |
2453 | +#define CON_STATE_PREOPEN 2 /* -> CONNECTING, CLOSED */ |
2454 | +#define CON_STATE_CONNECTING 3 /* -> NEGOTIATING, CLOSED */ |
2455 | +#define CON_STATE_NEGOTIATING 4 /* -> OPEN, CLOSED */ |
2456 | +#define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */ |
2457 | +#define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */ |
2458 | + |
2459 | +/* |
2460 | + * ceph_connection flag bits |
2461 | + */ |
2462 | +#define CON_FLAG_LOSSYTX 0 /* we can close channel or drop |
2463 | + * messages on errors */ |
2464 | +#define CON_FLAG_KEEPALIVE_PENDING 1 /* we need to send a keepalive */ |
2465 | +#define CON_FLAG_WRITE_PENDING 2 /* we have data ready to send */ |
2466 | +#define CON_FLAG_SOCK_CLOSED 3 /* socket state changed to closed */ |
2467 | +#define CON_FLAG_BACKOFF 4 /* need to retry queuing delayed work */ |
2468 | + |
2469 | /* static tag bytes (protocol control messages) */ |
2470 | static char tag_msg = CEPH_MSGR_TAG_MSG; |
2471 | static char tag_ack = CEPH_MSGR_TAG_ACK; |
2472 | @@ -147,72 +215,130 @@ void ceph_msgr_flush(void) |
2473 | } |
2474 | EXPORT_SYMBOL(ceph_msgr_flush); |
2475 | |
2476 | +/* Connection socket state transition functions */ |
2477 | + |
2478 | +static void con_sock_state_init(struct ceph_connection *con) |
2479 | +{ |
2480 | + int old_state; |
2481 | + |
2482 | + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); |
2483 | + if (WARN_ON(old_state != CON_SOCK_STATE_NEW)) |
2484 | + printk("%s: unexpected old state %d\n", __func__, old_state); |
2485 | + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, |
2486 | + CON_SOCK_STATE_CLOSED); |
2487 | +} |
2488 | + |
2489 | +static void con_sock_state_connecting(struct ceph_connection *con) |
2490 | +{ |
2491 | + int old_state; |
2492 | + |
2493 | + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING); |
2494 | + if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED)) |
2495 | + printk("%s: unexpected old state %d\n", __func__, old_state); |
2496 | + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, |
2497 | + CON_SOCK_STATE_CONNECTING); |
2498 | +} |
2499 | + |
2500 | +static void con_sock_state_connected(struct ceph_connection *con) |
2501 | +{ |
2502 | + int old_state; |
2503 | + |
2504 | + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED); |
2505 | + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING)) |
2506 | + printk("%s: unexpected old state %d\n", __func__, old_state); |
2507 | + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, |
2508 | + CON_SOCK_STATE_CONNECTED); |
2509 | +} |
2510 | + |
2511 | +static void con_sock_state_closing(struct ceph_connection *con) |
2512 | +{ |
2513 | + int old_state; |
2514 | + |
2515 | + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSING); |
2516 | + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING && |
2517 | + old_state != CON_SOCK_STATE_CONNECTED && |
2518 | + old_state != CON_SOCK_STATE_CLOSING)) |
2519 | + printk("%s: unexpected old state %d\n", __func__, old_state); |
2520 | + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, |
2521 | + CON_SOCK_STATE_CLOSING); |
2522 | +} |
2523 | + |
2524 | +static void con_sock_state_closed(struct ceph_connection *con) |
2525 | +{ |
2526 | + int old_state; |
2527 | + |
2528 | + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); |
2529 | + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && |
2530 | + old_state != CON_SOCK_STATE_CLOSING && |
2531 | + old_state != CON_SOCK_STATE_CONNECTING && |
2532 | + old_state != CON_SOCK_STATE_CLOSED)) |
2533 | + printk("%s: unexpected old state %d\n", __func__, old_state); |
2534 | + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, |
2535 | + CON_SOCK_STATE_CLOSED); |
2536 | +} |
2537 | |
2538 | /* |
2539 | * socket callback functions |
2540 | */ |
2541 | |
2542 | /* data available on socket, or listen socket received a connect */ |
2543 | -static void ceph_data_ready(struct sock *sk, int count_unused) |
2544 | +static void ceph_sock_data_ready(struct sock *sk, int count_unused) |
2545 | { |
2546 | struct ceph_connection *con = sk->sk_user_data; |
2547 | + if (atomic_read(&con->msgr->stopping)) { |
2548 | + return; |
2549 | + } |
2550 | |
2551 | if (sk->sk_state != TCP_CLOSE_WAIT) { |
2552 | - dout("ceph_data_ready on %p state = %lu, queueing work\n", |
2553 | + dout("%s on %p state = %lu, queueing work\n", __func__, |
2554 | con, con->state); |
2555 | queue_con(con); |
2556 | } |
2557 | } |
2558 | |
2559 | /* socket has buffer space for writing */ |
2560 | -static void ceph_write_space(struct sock *sk) |
2561 | +static void ceph_sock_write_space(struct sock *sk) |
2562 | { |
2563 | struct ceph_connection *con = sk->sk_user_data; |
2564 | |
2565 | /* only queue to workqueue if there is data we want to write, |
2566 | * and there is sufficient space in the socket buffer to accept |
2567 | - * more data. clear SOCK_NOSPACE so that ceph_write_space() |
2568 | + * more data. clear SOCK_NOSPACE so that ceph_sock_write_space() |
2569 | * doesn't get called again until try_write() fills the socket |
2570 | * buffer. See net/ipv4/tcp_input.c:tcp_check_space() |
2571 | * and net/core/stream.c:sk_stream_write_space(). |
2572 | */ |
2573 | - if (test_bit(WRITE_PENDING, &con->state)) { |
2574 | + if (test_bit(CON_FLAG_WRITE_PENDING, &con->flags)) { |
2575 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { |
2576 | - dout("ceph_write_space %p queueing write work\n", con); |
2577 | + dout("%s %p queueing write work\n", __func__, con); |
2578 | clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
2579 | queue_con(con); |
2580 | } |
2581 | } else { |
2582 | - dout("ceph_write_space %p nothing to write\n", con); |
2583 | + dout("%s %p nothing to write\n", __func__, con); |
2584 | } |
2585 | } |
2586 | |
2587 | /* socket's state has changed */ |
2588 | -static void ceph_state_change(struct sock *sk) |
2589 | +static void ceph_sock_state_change(struct sock *sk) |
2590 | { |
2591 | struct ceph_connection *con = sk->sk_user_data; |
2592 | |
2593 | - dout("ceph_state_change %p state = %lu sk_state = %u\n", |
2594 | + dout("%s %p state = %lu sk_state = %u\n", __func__, |
2595 | con, con->state, sk->sk_state); |
2596 | |
2597 | - if (test_bit(CLOSED, &con->state)) |
2598 | - return; |
2599 | - |
2600 | switch (sk->sk_state) { |
2601 | case TCP_CLOSE: |
2602 | - dout("ceph_state_change TCP_CLOSE\n"); |
2603 | + dout("%s TCP_CLOSE\n", __func__); |
2604 | case TCP_CLOSE_WAIT: |
2605 | - dout("ceph_state_change TCP_CLOSE_WAIT\n"); |
2606 | - if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) { |
2607 | - if (test_bit(CONNECTING, &con->state)) |
2608 | - con->error_msg = "connection failed"; |
2609 | - else |
2610 | - con->error_msg = "socket closed"; |
2611 | - queue_con(con); |
2612 | - } |
2613 | + dout("%s TCP_CLOSE_WAIT\n", __func__); |
2614 | + con_sock_state_closing(con); |
2615 | + set_bit(CON_FLAG_SOCK_CLOSED, &con->flags); |
2616 | + queue_con(con); |
2617 | break; |
2618 | case TCP_ESTABLISHED: |
2619 | - dout("ceph_state_change TCP_ESTABLISHED\n"); |
2620 | + dout("%s TCP_ESTABLISHED\n", __func__); |
2621 | + con_sock_state_connected(con); |
2622 | queue_con(con); |
2623 | break; |
2624 | default: /* Everything else is uninteresting */ |
2625 | @@ -228,9 +354,9 @@ static void set_sock_callbacks(struct socket *sock, |
2626 | { |
2627 | struct sock *sk = sock->sk; |
2628 | sk->sk_user_data = con; |
2629 | - sk->sk_data_ready = ceph_data_ready; |
2630 | - sk->sk_write_space = ceph_write_space; |
2631 | - sk->sk_state_change = ceph_state_change; |
2632 | + sk->sk_data_ready = ceph_sock_data_ready; |
2633 | + sk->sk_write_space = ceph_sock_write_space; |
2634 | + sk->sk_state_change = ceph_sock_state_change; |
2635 | } |
2636 | |
2637 | |
2638 | @@ -262,6 +388,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) |
2639 | |
2640 | dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr)); |
2641 | |
2642 | + con_sock_state_connecting(con); |
2643 | ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr), |
2644 | O_NONBLOCK); |
2645 | if (ret == -EINPROGRESS) { |
2646 | @@ -277,7 +404,6 @@ static int ceph_tcp_connect(struct ceph_connection *con) |
2647 | return ret; |
2648 | } |
2649 | con->sock = sock; |
2650 | - |
2651 | return 0; |
2652 | } |
2653 | |
2654 | @@ -333,16 +459,24 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, |
2655 | */ |
2656 | static int con_close_socket(struct ceph_connection *con) |
2657 | { |
2658 | - int rc; |
2659 | + int rc = 0; |
2660 | |
2661 | dout("con_close_socket on %p sock %p\n", con, con->sock); |
2662 | - if (!con->sock) |
2663 | - return 0; |
2664 | - set_bit(SOCK_CLOSED, &con->state); |
2665 | - rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); |
2666 | - sock_release(con->sock); |
2667 | - con->sock = NULL; |
2668 | - clear_bit(SOCK_CLOSED, &con->state); |
2669 | + if (con->sock) { |
2670 | + rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); |
2671 | + sock_release(con->sock); |
2672 | + con->sock = NULL; |
2673 | + } |
2674 | + |
2675 | + /* |
2676 | + * Forcibly clear the SOCK_CLOSED flag. It gets set |
2677 | + * independent of the connection mutex, and we could have |
2678 | + * received a socket close event before we had the chance to |
2679 | + * shut the socket down. |
2680 | + */ |
2681 | + clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags); |
2682 | + |
2683 | + con_sock_state_closed(con); |
2684 | return rc; |
2685 | } |
2686 | |
2687 | @@ -353,6 +487,10 @@ static int con_close_socket(struct ceph_connection *con) |
2688 | static void ceph_msg_remove(struct ceph_msg *msg) |
2689 | { |
2690 | list_del_init(&msg->list_head); |
2691 | + BUG_ON(msg->con == NULL); |
2692 | + msg->con->ops->put(msg->con); |
2693 | + msg->con = NULL; |
2694 | + |
2695 | ceph_msg_put(msg); |
2696 | } |
2697 | static void ceph_msg_remove_list(struct list_head *head) |
2698 | @@ -372,8 +510,11 @@ static void reset_connection(struct ceph_connection *con) |
2699 | ceph_msg_remove_list(&con->out_sent); |
2700 | |
2701 | if (con->in_msg) { |
2702 | + BUG_ON(con->in_msg->con != con); |
2703 | + con->in_msg->con = NULL; |
2704 | ceph_msg_put(con->in_msg); |
2705 | con->in_msg = NULL; |
2706 | + con->ops->put(con); |
2707 | } |
2708 | |
2709 | con->connect_seq = 0; |
2710 | @@ -391,32 +532,44 @@ static void reset_connection(struct ceph_connection *con) |
2711 | */ |
2712 | void ceph_con_close(struct ceph_connection *con) |
2713 | { |
2714 | + mutex_lock(&con->mutex); |
2715 | dout("con_close %p peer %s\n", con, |
2716 | ceph_pr_addr(&con->peer_addr.in_addr)); |
2717 | - set_bit(CLOSED, &con->state); /* in case there's queued work */ |
2718 | - clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ |
2719 | - clear_bit(LOSSYTX, &con->state); /* so we retry next connect */ |
2720 | - clear_bit(KEEPALIVE_PENDING, &con->state); |
2721 | - clear_bit(WRITE_PENDING, &con->state); |
2722 | - mutex_lock(&con->mutex); |
2723 | + con->state = CON_STATE_CLOSED; |
2724 | + |
2725 | + clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */ |
2726 | + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); |
2727 | + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
2728 | + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); |
2729 | + clear_bit(CON_FLAG_BACKOFF, &con->flags); |
2730 | + |
2731 | reset_connection(con); |
2732 | con->peer_global_seq = 0; |
2733 | cancel_delayed_work(&con->work); |
2734 | + con_close_socket(con); |
2735 | mutex_unlock(&con->mutex); |
2736 | - queue_con(con); |
2737 | } |
2738 | EXPORT_SYMBOL(ceph_con_close); |
2739 | |
2740 | /* |
2741 | * Reopen a closed connection, with a new peer address. |
2742 | */ |
2743 | -void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr) |
2744 | +void ceph_con_open(struct ceph_connection *con, |
2745 | + __u8 entity_type, __u64 entity_num, |
2746 | + struct ceph_entity_addr *addr) |
2747 | { |
2748 | + mutex_lock(&con->mutex); |
2749 | dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); |
2750 | - set_bit(OPENING, &con->state); |
2751 | - clear_bit(CLOSED, &con->state); |
2752 | + |
2753 | + BUG_ON(con->state != CON_STATE_CLOSED); |
2754 | + con->state = CON_STATE_PREOPEN; |
2755 | + |
2756 | + con->peer_name.type = (__u8) entity_type; |
2757 | + con->peer_name.num = cpu_to_le64(entity_num); |
2758 | + |
2759 | memcpy(&con->peer_addr, addr, sizeof(*addr)); |
2760 | con->delay = 0; /* reset backoff memory */ |
2761 | + mutex_unlock(&con->mutex); |
2762 | queue_con(con); |
2763 | } |
2764 | EXPORT_SYMBOL(ceph_con_open); |
2765 | @@ -430,42 +583,26 @@ bool ceph_con_opened(struct ceph_connection *con) |
2766 | } |
2767 | |
2768 | /* |
2769 | - * generic get/put |
2770 | - */ |
2771 | -struct ceph_connection *ceph_con_get(struct ceph_connection *con) |
2772 | -{ |
2773 | - int nref = __atomic_add_unless(&con->nref, 1, 0); |
2774 | - |
2775 | - dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1); |
2776 | - |
2777 | - return nref ? con : NULL; |
2778 | -} |
2779 | - |
2780 | -void ceph_con_put(struct ceph_connection *con) |
2781 | -{ |
2782 | - int nref = atomic_dec_return(&con->nref); |
2783 | - |
2784 | - BUG_ON(nref < 0); |
2785 | - if (nref == 0) { |
2786 | - BUG_ON(con->sock); |
2787 | - kfree(con); |
2788 | - } |
2789 | - dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref); |
2790 | -} |
2791 | - |
2792 | -/* |
2793 | * initialize a new connection. |
2794 | */ |
2795 | -void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) |
2796 | +void ceph_con_init(struct ceph_connection *con, void *private, |
2797 | + const struct ceph_connection_operations *ops, |
2798 | + struct ceph_messenger *msgr) |
2799 | { |
2800 | dout("con_init %p\n", con); |
2801 | memset(con, 0, sizeof(*con)); |
2802 | - atomic_set(&con->nref, 1); |
2803 | + con->private = private; |
2804 | + con->ops = ops; |
2805 | con->msgr = msgr; |
2806 | + |
2807 | + con_sock_state_init(con); |
2808 | + |
2809 | mutex_init(&con->mutex); |
2810 | INIT_LIST_HEAD(&con->out_queue); |
2811 | INIT_LIST_HEAD(&con->out_sent); |
2812 | INIT_DELAYED_WORK(&con->work, con_work); |
2813 | + |
2814 | + con->state = CON_STATE_CLOSED; |
2815 | } |
2816 | EXPORT_SYMBOL(ceph_con_init); |
2817 | |
2818 | @@ -486,14 +623,14 @@ static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt) |
2819 | return ret; |
2820 | } |
2821 | |
2822 | -static void ceph_con_out_kvec_reset(struct ceph_connection *con) |
2823 | +static void con_out_kvec_reset(struct ceph_connection *con) |
2824 | { |
2825 | con->out_kvec_left = 0; |
2826 | con->out_kvec_bytes = 0; |
2827 | con->out_kvec_cur = &con->out_kvec[0]; |
2828 | } |
2829 | |
2830 | -static void ceph_con_out_kvec_add(struct ceph_connection *con, |
2831 | +static void con_out_kvec_add(struct ceph_connection *con, |
2832 | size_t size, void *data) |
2833 | { |
2834 | int index; |
2835 | @@ -507,6 +644,53 @@ static void ceph_con_out_kvec_add(struct ceph_connection *con, |
2836 | con->out_kvec_bytes += size; |
2837 | } |
2838 | |
2839 | +#ifdef CONFIG_BLOCK |
2840 | +static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) |
2841 | +{ |
2842 | + if (!bio) { |
2843 | + *iter = NULL; |
2844 | + *seg = 0; |
2845 | + return; |
2846 | + } |
2847 | + *iter = bio; |
2848 | + *seg = bio->bi_idx; |
2849 | +} |
2850 | + |
2851 | +static void iter_bio_next(struct bio **bio_iter, int *seg) |
2852 | +{ |
2853 | + if (*bio_iter == NULL) |
2854 | + return; |
2855 | + |
2856 | + BUG_ON(*seg >= (*bio_iter)->bi_vcnt); |
2857 | + |
2858 | + (*seg)++; |
2859 | + if (*seg == (*bio_iter)->bi_vcnt) |
2860 | + init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); |
2861 | +} |
2862 | +#endif |
2863 | + |
2864 | +static void prepare_write_message_data(struct ceph_connection *con) |
2865 | +{ |
2866 | + struct ceph_msg *msg = con->out_msg; |
2867 | + |
2868 | + BUG_ON(!msg); |
2869 | + BUG_ON(!msg->hdr.data_len); |
2870 | + |
2871 | + /* initialize page iterator */ |
2872 | + con->out_msg_pos.page = 0; |
2873 | + if (msg->pages) |
2874 | + con->out_msg_pos.page_pos = msg->page_alignment; |
2875 | + else |
2876 | + con->out_msg_pos.page_pos = 0; |
2877 | +#ifdef CONFIG_BLOCK |
2878 | + if (msg->bio) |
2879 | + init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); |
2880 | +#endif |
2881 | + con->out_msg_pos.data_pos = 0; |
2882 | + con->out_msg_pos.did_page_crc = false; |
2883 | + con->out_more = 1; /* data + footer will follow */ |
2884 | +} |
2885 | + |
2886 | /* |
2887 | * Prepare footer for currently outgoing message, and finish things |
2888 | * off. Assumes out_kvec* are already valid.. we just add on to the end. |
2889 | @@ -516,6 +700,8 @@ static void prepare_write_message_footer(struct ceph_connection *con) |
2890 | struct ceph_msg *m = con->out_msg; |
2891 | int v = con->out_kvec_left; |
2892 | |
2893 | + m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; |
2894 | + |
2895 | dout("prepare_write_message_footer %p\n", con); |
2896 | con->out_kvec_is_msg = true; |
2897 | con->out_kvec[v].iov_base = &m->footer; |
2898 | @@ -534,7 +720,7 @@ static void prepare_write_message(struct ceph_connection *con) |
2899 | struct ceph_msg *m; |
2900 | u32 crc; |
2901 | |
2902 | - ceph_con_out_kvec_reset(con); |
2903 | + con_out_kvec_reset(con); |
2904 | con->out_kvec_is_msg = true; |
2905 | con->out_msg_done = false; |
2906 | |
2907 | @@ -542,14 +728,16 @@ static void prepare_write_message(struct ceph_connection *con) |
2908 | * TCP packet that's a good thing. */ |
2909 | if (con->in_seq > con->in_seq_acked) { |
2910 | con->in_seq_acked = con->in_seq; |
2911 | - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); |
2912 | + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); |
2913 | con->out_temp_ack = cpu_to_le64(con->in_seq_acked); |
2914 | - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), |
2915 | + con_out_kvec_add(con, sizeof (con->out_temp_ack), |
2916 | &con->out_temp_ack); |
2917 | } |
2918 | |
2919 | + BUG_ON(list_empty(&con->out_queue)); |
2920 | m = list_first_entry(&con->out_queue, struct ceph_msg, list_head); |
2921 | con->out_msg = m; |
2922 | + BUG_ON(m->con != con); |
2923 | |
2924 | /* put message on sent list */ |
2925 | ceph_msg_get(m); |
2926 | @@ -572,18 +760,18 @@ static void prepare_write_message(struct ceph_connection *con) |
2927 | BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len); |
2928 | |
2929 | /* tag + hdr + front + middle */ |
2930 | - ceph_con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); |
2931 | - ceph_con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); |
2932 | - ceph_con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); |
2933 | + con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); |
2934 | + con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); |
2935 | + con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); |
2936 | |
2937 | if (m->middle) |
2938 | - ceph_con_out_kvec_add(con, m->middle->vec.iov_len, |
2939 | + con_out_kvec_add(con, m->middle->vec.iov_len, |
2940 | m->middle->vec.iov_base); |
2941 | |
2942 | /* fill in crc (except data pages), footer */ |
2943 | crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); |
2944 | con->out_msg->hdr.crc = cpu_to_le32(crc); |
2945 | - con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE; |
2946 | + con->out_msg->footer.flags = 0; |
2947 | |
2948 | crc = crc32c(0, m->front.iov_base, m->front.iov_len); |
2949 | con->out_msg->footer.front_crc = cpu_to_le32(crc); |
2950 | @@ -593,28 +781,19 @@ static void prepare_write_message(struct ceph_connection *con) |
2951 | con->out_msg->footer.middle_crc = cpu_to_le32(crc); |
2952 | } else |
2953 | con->out_msg->footer.middle_crc = 0; |
2954 | - con->out_msg->footer.data_crc = 0; |
2955 | - dout("prepare_write_message front_crc %u data_crc %u\n", |
2956 | + dout("%s front_crc %u middle_crc %u\n", __func__, |
2957 | le32_to_cpu(con->out_msg->footer.front_crc), |
2958 | le32_to_cpu(con->out_msg->footer.middle_crc)); |
2959 | |
2960 | /* is there a data payload? */ |
2961 | - if (le32_to_cpu(m->hdr.data_len) > 0) { |
2962 | - /* initialize page iterator */ |
2963 | - con->out_msg_pos.page = 0; |
2964 | - if (m->pages) |
2965 | - con->out_msg_pos.page_pos = m->page_alignment; |
2966 | - else |
2967 | - con->out_msg_pos.page_pos = 0; |
2968 | - con->out_msg_pos.data_pos = 0; |
2969 | - con->out_msg_pos.did_page_crc = false; |
2970 | - con->out_more = 1; /* data + footer will follow */ |
2971 | - } else { |
2972 | + con->out_msg->footer.data_crc = 0; |
2973 | + if (m->hdr.data_len) |
2974 | + prepare_write_message_data(con); |
2975 | + else |
2976 | /* no, queue up footer too and be done */ |
2977 | prepare_write_message_footer(con); |
2978 | - } |
2979 | |
2980 | - set_bit(WRITE_PENDING, &con->state); |
2981 | + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
2982 | } |
2983 | |
2984 | /* |
2985 | @@ -626,16 +805,16 @@ static void prepare_write_ack(struct ceph_connection *con) |
2986 | con->in_seq_acked, con->in_seq); |
2987 | con->in_seq_acked = con->in_seq; |
2988 | |
2989 | - ceph_con_out_kvec_reset(con); |
2990 | + con_out_kvec_reset(con); |
2991 | |
2992 | - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); |
2993 | + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); |
2994 | |
2995 | con->out_temp_ack = cpu_to_le64(con->in_seq_acked); |
2996 | - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), |
2997 | + con_out_kvec_add(con, sizeof (con->out_temp_ack), |
2998 | &con->out_temp_ack); |
2999 | |
3000 | con->out_more = 1; /* more will follow.. eventually.. */ |
3001 | - set_bit(WRITE_PENDING, &con->state); |
3002 | + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
3003 | } |
3004 | |
3005 | /* |
3006 | @@ -644,63 +823,60 @@ static void prepare_write_ack(struct ceph_connection *con) |
3007 | static void prepare_write_keepalive(struct ceph_connection *con) |
3008 | { |
3009 | dout("prepare_write_keepalive %p\n", con); |
3010 | - ceph_con_out_kvec_reset(con); |
3011 | - ceph_con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); |
3012 | - set_bit(WRITE_PENDING, &con->state); |
3013 | + con_out_kvec_reset(con); |
3014 | + con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); |
3015 | + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
3016 | } |
3017 | |
3018 | /* |
3019 | * Connection negotiation. |
3020 | */ |
3021 | |
3022 | -static int prepare_connect_authorizer(struct ceph_connection *con) |
3023 | +static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con, |
3024 | + int *auth_proto) |
3025 | { |
3026 | - void *auth_buf; |
3027 | - int auth_len = 0; |
3028 | - int auth_protocol = 0; |
3029 | + struct ceph_auth_handshake *auth; |
3030 | + |
3031 | + if (!con->ops->get_authorizer) { |
3032 | + con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; |
3033 | + con->out_connect.authorizer_len = 0; |
3034 | + return NULL; |
3035 | + } |
3036 | |
3037 | + /* Can't hold the mutex while getting authorizer */ |
3038 | mutex_unlock(&con->mutex); |
3039 | - if (con->ops->get_authorizer) |
3040 | - con->ops->get_authorizer(con, &auth_buf, &auth_len, |
3041 | - &auth_protocol, &con->auth_reply_buf, |
3042 | - &con->auth_reply_buf_len, |
3043 | - con->auth_retry); |
3044 | + auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry); |
3045 | mutex_lock(&con->mutex); |
3046 | |
3047 | - if (test_bit(CLOSED, &con->state) || |
3048 | - test_bit(OPENING, &con->state)) |
3049 | - return -EAGAIN; |
3050 | + if (IS_ERR(auth)) |
3051 | + return auth; |
3052 | + if (con->state != CON_STATE_NEGOTIATING) |
3053 | + return ERR_PTR(-EAGAIN); |
3054 | |
3055 | - con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); |
3056 | - con->out_connect.authorizer_len = cpu_to_le32(auth_len); |
3057 | - |
3058 | - if (auth_len) |
3059 | - ceph_con_out_kvec_add(con, auth_len, auth_buf); |
3060 | - |
3061 | - return 0; |
3062 | + con->auth_reply_buf = auth->authorizer_reply_buf; |
3063 | + con->auth_reply_buf_len = auth->authorizer_reply_buf_len; |
3064 | + return auth; |
3065 | } |
3066 | |
3067 | /* |
3068 | * We connected to a peer and are saying hello. |
3069 | */ |
3070 | -static void prepare_write_banner(struct ceph_messenger *msgr, |
3071 | - struct ceph_connection *con) |
3072 | +static void prepare_write_banner(struct ceph_connection *con) |
3073 | { |
3074 | - ceph_con_out_kvec_reset(con); |
3075 | - ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); |
3076 | - ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr), |
3077 | - &msgr->my_enc_addr); |
3078 | + con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); |
3079 | + con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), |
3080 | + &con->msgr->my_enc_addr); |
3081 | |
3082 | con->out_more = 0; |
3083 | - set_bit(WRITE_PENDING, &con->state); |
3084 | + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
3085 | } |
3086 | |
3087 | -static int prepare_write_connect(struct ceph_messenger *msgr, |
3088 | - struct ceph_connection *con, |
3089 | - int include_banner) |
3090 | +static int prepare_write_connect(struct ceph_connection *con) |
3091 | { |
3092 | unsigned global_seq = get_global_seq(con->msgr, 0); |
3093 | int proto; |
3094 | + int auth_proto; |
3095 | + struct ceph_auth_handshake *auth; |
3096 | |
3097 | switch (con->peer_name.type) { |
3098 | case CEPH_ENTITY_TYPE_MON: |
3099 | @@ -719,23 +895,32 @@ static int prepare_write_connect(struct ceph_messenger *msgr, |
3100 | dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, |
3101 | con->connect_seq, global_seq, proto); |
3102 | |
3103 | - con->out_connect.features = cpu_to_le64(msgr->supported_features); |
3104 | + con->out_connect.features = cpu_to_le64(con->msgr->supported_features); |
3105 | con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); |
3106 | con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); |
3107 | con->out_connect.global_seq = cpu_to_le32(global_seq); |
3108 | con->out_connect.protocol_version = cpu_to_le32(proto); |
3109 | con->out_connect.flags = 0; |
3110 | |
3111 | - if (include_banner) |
3112 | - prepare_write_banner(msgr, con); |
3113 | - else |
3114 | - ceph_con_out_kvec_reset(con); |
3115 | - ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); |
3116 | + auth_proto = CEPH_AUTH_UNKNOWN; |
3117 | + auth = get_connect_authorizer(con, &auth_proto); |
3118 | + if (IS_ERR(auth)) |
3119 | + return PTR_ERR(auth); |
3120 | + |
3121 | + con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto); |
3122 | + con->out_connect.authorizer_len = auth ? |
3123 | + cpu_to_le32(auth->authorizer_buf_len) : 0; |
3124 | + |
3125 | + con_out_kvec_add(con, sizeof (con->out_connect), |
3126 | + &con->out_connect); |
3127 | + if (auth && auth->authorizer_buf_len) |
3128 | + con_out_kvec_add(con, auth->authorizer_buf_len, |
3129 | + auth->authorizer_buf); |
3130 | |
3131 | con->out_more = 0; |
3132 | - set_bit(WRITE_PENDING, &con->state); |
3133 | + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
3134 | |
3135 | - return prepare_connect_authorizer(con); |
3136 | + return 0; |
3137 | } |
3138 | |
3139 | /* |
3140 | @@ -781,30 +966,34 @@ out: |
3141 | return ret; /* done! */ |
3142 | } |
3143 | |
3144 | -#ifdef CONFIG_BLOCK |
3145 | -static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) |
3146 | +static void out_msg_pos_next(struct ceph_connection *con, struct page *page, |
3147 | + size_t len, size_t sent, bool in_trail) |
3148 | { |
3149 | - if (!bio) { |
3150 | - *iter = NULL; |
3151 | - *seg = 0; |
3152 | - return; |
3153 | - } |
3154 | - *iter = bio; |
3155 | - *seg = bio->bi_idx; |
3156 | -} |
3157 | + struct ceph_msg *msg = con->out_msg; |
3158 | |
3159 | -static void iter_bio_next(struct bio **bio_iter, int *seg) |
3160 | -{ |
3161 | - if (*bio_iter == NULL) |
3162 | - return; |
3163 | + BUG_ON(!msg); |
3164 | + BUG_ON(!sent); |
3165 | |
3166 | - BUG_ON(*seg >= (*bio_iter)->bi_vcnt); |
3167 | + con->out_msg_pos.data_pos += sent; |
3168 | + con->out_msg_pos.page_pos += sent; |
3169 | + if (sent < len) |
3170 | + return; |
3171 | |
3172 | - (*seg)++; |
3173 | - if (*seg == (*bio_iter)->bi_vcnt) |
3174 | - init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); |
3175 | -} |
3176 | + BUG_ON(sent != len); |
3177 | + con->out_msg_pos.page_pos = 0; |
3178 | + con->out_msg_pos.page++; |
3179 | + con->out_msg_pos.did_page_crc = false; |
3180 | + if (in_trail) |
3181 | + list_move_tail(&page->lru, |
3182 | + &msg->trail->head); |
3183 | + else if (msg->pagelist) |
3184 | + list_move_tail(&page->lru, |
3185 | + &msg->pagelist->head); |
3186 | +#ifdef CONFIG_BLOCK |
3187 | + else if (msg->bio) |
3188 | + iter_bio_next(&msg->bio_iter, &msg->bio_seg); |
3189 | #endif |
3190 | +} |
3191 | |
3192 | /* |
3193 | * Write as much message data payload as we can. If we finish, queue |
3194 | @@ -821,41 +1010,36 @@ static int write_partial_msg_pages(struct ceph_connection *con) |
3195 | bool do_datacrc = !con->msgr->nocrc; |
3196 | int ret; |
3197 | int total_max_write; |
3198 | - int in_trail = 0; |
3199 | - size_t trail_len = (msg->trail ? msg->trail->length : 0); |
3200 | + bool in_trail = false; |
3201 | + const size_t trail_len = (msg->trail ? msg->trail->length : 0); |
3202 | + const size_t trail_off = data_len - trail_len; |
3203 | |
3204 | dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", |
3205 | - con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages, |
3206 | + con, msg, con->out_msg_pos.page, msg->nr_pages, |
3207 | con->out_msg_pos.page_pos); |
3208 | |
3209 | -#ifdef CONFIG_BLOCK |
3210 | - if (msg->bio && !msg->bio_iter) |
3211 | - init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); |
3212 | -#endif |
3213 | - |
3214 | + /* |
3215 | + * Iterate through each page that contains data to be |
3216 | + * written, and send as much as possible for each. |
3217 | + * |
3218 | + * If we are calculating the data crc (the default), we will |
3219 | + * need to map the page. If we have no pages, they have |
3220 | + * been revoked, so use the zero page. |
3221 | + */ |
3222 | while (data_len > con->out_msg_pos.data_pos) { |
3223 | struct page *page = NULL; |
3224 | int max_write = PAGE_SIZE; |
3225 | int bio_offset = 0; |
3226 | |
3227 | - total_max_write = data_len - trail_len - |
3228 | - con->out_msg_pos.data_pos; |
3229 | - |
3230 | - /* |
3231 | - * if we are calculating the data crc (the default), we need |
3232 | - * to map the page. if our pages[] has been revoked, use the |
3233 | - * zero page. |
3234 | - */ |
3235 | - |
3236 | - /* have we reached the trail part of the data? */ |
3237 | - if (con->out_msg_pos.data_pos >= data_len - trail_len) { |
3238 | - in_trail = 1; |
3239 | + in_trail = in_trail || con->out_msg_pos.data_pos >= trail_off; |
3240 | + if (!in_trail) |
3241 | + total_max_write = trail_off - con->out_msg_pos.data_pos; |
3242 | |
3243 | + if (in_trail) { |
3244 | total_max_write = data_len - con->out_msg_pos.data_pos; |
3245 | |
3246 | page = list_first_entry(&msg->trail->head, |
3247 | struct page, lru); |
3248 | - max_write = PAGE_SIZE; |
3249 | } else if (msg->pages) { |
3250 | page = msg->pages[con->out_msg_pos.page]; |
3251 | } else if (msg->pagelist) { |
3252 | @@ -878,52 +1062,32 @@ static int write_partial_msg_pages(struct ceph_connection *con) |
3253 | |
3254 | if (do_datacrc && !con->out_msg_pos.did_page_crc) { |
3255 | void *base; |
3256 | - u32 crc; |
3257 | - u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); |
3258 | + u32 crc = le32_to_cpu(msg->footer.data_crc); |
3259 | char *kaddr; |
3260 | |
3261 | kaddr = kmap(page); |
3262 | BUG_ON(kaddr == NULL); |
3263 | base = kaddr + con->out_msg_pos.page_pos + bio_offset; |
3264 | - crc = crc32c(tmpcrc, base, len); |
3265 | - con->out_msg->footer.data_crc = cpu_to_le32(crc); |
3266 | + crc = crc32c(crc, base, len); |
3267 | + kunmap(page); |
3268 | + msg->footer.data_crc = cpu_to_le32(crc); |
3269 | con->out_msg_pos.did_page_crc = true; |
3270 | } |
3271 | ret = ceph_tcp_sendpage(con->sock, page, |
3272 | con->out_msg_pos.page_pos + bio_offset, |
3273 | len, 1); |
3274 | - |
3275 | - if (do_datacrc) |
3276 | - kunmap(page); |
3277 | - |
3278 | if (ret <= 0) |
3279 | goto out; |
3280 | |
3281 | - con->out_msg_pos.data_pos += ret; |
3282 | - con->out_msg_pos.page_pos += ret; |
3283 | - if (ret == len) { |
3284 | - con->out_msg_pos.page_pos = 0; |
3285 | - con->out_msg_pos.page++; |
3286 | - con->out_msg_pos.did_page_crc = false; |
3287 | - if (in_trail) |
3288 | - list_move_tail(&page->lru, |
3289 | - &msg->trail->head); |
3290 | - else if (msg->pagelist) |
3291 | - list_move_tail(&page->lru, |
3292 | - &msg->pagelist->head); |
3293 | -#ifdef CONFIG_BLOCK |
3294 | - else if (msg->bio) |
3295 | - iter_bio_next(&msg->bio_iter, &msg->bio_seg); |
3296 | -#endif |
3297 | - } |
3298 | + out_msg_pos_next(con, page, len, (size_t) ret, in_trail); |
3299 | } |
3300 | |
3301 | dout("write_partial_msg_pages %p msg %p done\n", con, msg); |
3302 | |
3303 | /* prepare and queue up footer, too */ |
3304 | if (!do_datacrc) |
3305 | - con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; |
3306 | - ceph_con_out_kvec_reset(con); |
3307 | + msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; |
3308 | + con_out_kvec_reset(con); |
3309 | prepare_write_message_footer(con); |
3310 | ret = 1; |
3311 | out: |
3312 | @@ -992,11 +1156,10 @@ static int prepare_read_message(struct ceph_connection *con) |
3313 | |
3314 | |
3315 | static int read_partial(struct ceph_connection *con, |
3316 | - int *to, int size, void *object) |
3317 | + int end, int size, void *object) |
3318 | { |
3319 | - *to += size; |
3320 | - while (con->in_base_pos < *to) { |
3321 | - int left = *to - con->in_base_pos; |
3322 | + while (con->in_base_pos < end) { |
3323 | + int left = end - con->in_base_pos; |
3324 | int have = size - left; |
3325 | int ret = ceph_tcp_recvmsg(con->sock, object + have, left); |
3326 | if (ret <= 0) |
3327 | @@ -1012,37 +1175,52 @@ static int read_partial(struct ceph_connection *con, |
3328 | */ |
3329 | static int read_partial_banner(struct ceph_connection *con) |
3330 | { |
3331 | - int ret, to = 0; |
3332 | + int size; |
3333 | + int end; |
3334 | + int ret; |
3335 | |
3336 | dout("read_partial_banner %p at %d\n", con, con->in_base_pos); |
3337 | |
3338 | /* peer's banner */ |
3339 | - ret = read_partial(con, &to, strlen(CEPH_BANNER), con->in_banner); |
3340 | + size = strlen(CEPH_BANNER); |
3341 | + end = size; |
3342 | + ret = read_partial(con, end, size, con->in_banner); |
3343 | if (ret <= 0) |
3344 | goto out; |
3345 | - ret = read_partial(con, &to, sizeof(con->actual_peer_addr), |
3346 | - &con->actual_peer_addr); |
3347 | + |
3348 | + size = sizeof (con->actual_peer_addr); |
3349 | + end += size; |
3350 | + ret = read_partial(con, end, size, &con->actual_peer_addr); |
3351 | if (ret <= 0) |
3352 | goto out; |
3353 | - ret = read_partial(con, &to, sizeof(con->peer_addr_for_me), |
3354 | - &con->peer_addr_for_me); |
3355 | + |
3356 | + size = sizeof (con->peer_addr_for_me); |
3357 | + end += size; |
3358 | + ret = read_partial(con, end, size, &con->peer_addr_for_me); |
3359 | if (ret <= 0) |
3360 | goto out; |
3361 | + |
3362 | out: |
3363 | return ret; |
3364 | } |
3365 | |
3366 | static int read_partial_connect(struct ceph_connection *con) |
3367 | { |
3368 | - int ret, to = 0; |
3369 | + int size; |
3370 | + int end; |
3371 | + int ret; |
3372 | |
3373 | dout("read_partial_connect %p at %d\n", con, con->in_base_pos); |
3374 | |
3375 | - ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply); |
3376 | + size = sizeof (con->in_reply); |
3377 | + end = size; |
3378 | + ret = read_partial(con, end, size, &con->in_reply); |
3379 | if (ret <= 0) |
3380 | goto out; |
3381 | - ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len), |
3382 | - con->auth_reply_buf); |
3383 | + |
3384 | + size = le32_to_cpu(con->in_reply.authorizer_len); |
3385 | + end += size; |
3386 | + ret = read_partial(con, end, size, con->auth_reply_buf); |
3387 | if (ret <= 0) |
3388 | goto out; |
3389 | |
3390 | @@ -1321,20 +1499,14 @@ static int process_banner(struct ceph_connection *con) |
3391 | ceph_pr_addr(&con->msgr->inst.addr.in_addr)); |
3392 | } |
3393 | |
3394 | - set_bit(NEGOTIATING, &con->state); |
3395 | - prepare_read_connect(con); |
3396 | return 0; |
3397 | } |
3398 | |
3399 | static void fail_protocol(struct ceph_connection *con) |
3400 | { |
3401 | reset_connection(con); |
3402 | - set_bit(CLOSED, &con->state); /* in case there's queued work */ |
3403 | - |
3404 | - mutex_unlock(&con->mutex); |
3405 | - if (con->ops->bad_proto) |
3406 | - con->ops->bad_proto(con); |
3407 | - mutex_lock(&con->mutex); |
3408 | + BUG_ON(con->state != CON_STATE_NEGOTIATING); |
3409 | + con->state = CON_STATE_CLOSED; |
3410 | } |
3411 | |
3412 | static int process_connect(struct ceph_connection *con) |
3413 | @@ -1377,7 +1549,8 @@ static int process_connect(struct ceph_connection *con) |
3414 | return -1; |
3415 | } |
3416 | con->auth_retry = 1; |
3417 | - ret = prepare_write_connect(con->msgr, con, 0); |
3418 | + con_out_kvec_reset(con); |
3419 | + ret = prepare_write_connect(con); |
3420 | if (ret < 0) |
3421 | return ret; |
3422 | prepare_read_connect(con); |
3423 | @@ -1392,12 +1565,15 @@ static int process_connect(struct ceph_connection *con) |
3424 | * dropped messages. |
3425 | */ |
3426 | dout("process_connect got RESET peer seq %u\n", |
3427 | - le32_to_cpu(con->in_connect.connect_seq)); |
3428 | + le32_to_cpu(con->in_reply.connect_seq)); |
3429 | pr_err("%s%lld %s connection reset\n", |
3430 | ENTITY_NAME(con->peer_name), |
3431 | ceph_pr_addr(&con->peer_addr.in_addr)); |
3432 | reset_connection(con); |
3433 | - prepare_write_connect(con->msgr, con, 0); |
3434 | + con_out_kvec_reset(con); |
3435 | + ret = prepare_write_connect(con); |
3436 | + if (ret < 0) |
3437 | + return ret; |
3438 | prepare_read_connect(con); |
3439 | |
3440 | /* Tell ceph about it. */ |
3441 | @@ -1406,8 +1582,7 @@ static int process_connect(struct ceph_connection *con) |
3442 | if (con->ops->peer_reset) |
3443 | con->ops->peer_reset(con); |
3444 | mutex_lock(&con->mutex); |
3445 | - if (test_bit(CLOSED, &con->state) || |
3446 | - test_bit(OPENING, &con->state)) |
3447 | + if (con->state != CON_STATE_NEGOTIATING) |
3448 | return -EAGAIN; |
3449 | break; |
3450 | |
3451 | @@ -1416,11 +1591,14 @@ static int process_connect(struct ceph_connection *con) |
3452 | * If we sent a smaller connect_seq than the peer has, try |
3453 | * again with a larger value. |
3454 | */ |
3455 | - dout("process_connect got RETRY my seq = %u, peer_seq = %u\n", |
3456 | + dout("process_connect got RETRY_SESSION my seq %u, peer %u\n", |
3457 | le32_to_cpu(con->out_connect.connect_seq), |
3458 | - le32_to_cpu(con->in_connect.connect_seq)); |
3459 | - con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); |
3460 | - prepare_write_connect(con->msgr, con, 0); |
3461 | + le32_to_cpu(con->in_reply.connect_seq)); |
3462 | + con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); |
3463 | + con_out_kvec_reset(con); |
3464 | + ret = prepare_write_connect(con); |
3465 | + if (ret < 0) |
3466 | + return ret; |
3467 | prepare_read_connect(con); |
3468 | break; |
3469 | |
3470 | @@ -1431,10 +1609,13 @@ static int process_connect(struct ceph_connection *con) |
3471 | */ |
3472 | dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n", |
3473 | con->peer_global_seq, |
3474 | - le32_to_cpu(con->in_connect.global_seq)); |
3475 | + le32_to_cpu(con->in_reply.global_seq)); |
3476 | get_global_seq(con->msgr, |
3477 | - le32_to_cpu(con->in_connect.global_seq)); |
3478 | - prepare_write_connect(con->msgr, con, 0); |
3479 | + le32_to_cpu(con->in_reply.global_seq)); |
3480 | + con_out_kvec_reset(con); |
3481 | + ret = prepare_write_connect(con); |
3482 | + if (ret < 0) |
3483 | + return ret; |
3484 | prepare_read_connect(con); |
3485 | break; |
3486 | |
3487 | @@ -1449,7 +1630,10 @@ static int process_connect(struct ceph_connection *con) |
3488 | fail_protocol(con); |
3489 | return -1; |
3490 | } |
3491 | - clear_bit(CONNECTING, &con->state); |
3492 | + |
3493 | + BUG_ON(con->state != CON_STATE_NEGOTIATING); |
3494 | + con->state = CON_STATE_OPEN; |
3495 | + |
3496 | con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); |
3497 | con->connect_seq++; |
3498 | con->peer_features = server_feat; |
3499 | @@ -1461,7 +1645,9 @@ static int process_connect(struct ceph_connection *con) |
3500 | le32_to_cpu(con->in_reply.connect_seq)); |
3501 | |
3502 | if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) |
3503 | - set_bit(LOSSYTX, &con->state); |
3504 | + set_bit(CON_FLAG_LOSSYTX, &con->flags); |
3505 | + |
3506 | + con->delay = 0; /* reset backoff memory */ |
3507 | |
3508 | prepare_read_tag(con); |
3509 | break; |
3510 | @@ -1491,10 +1677,10 @@ static int process_connect(struct ceph_connection *con) |
3511 | */ |
3512 | static int read_partial_ack(struct ceph_connection *con) |
3513 | { |
3514 | - int to = 0; |
3515 | + int size = sizeof (con->in_temp_ack); |
3516 | + int end = size; |
3517 | |
3518 | - return read_partial(con, &to, sizeof(con->in_temp_ack), |
3519 | - &con->in_temp_ack); |
3520 | + return read_partial(con, end, size, &con->in_temp_ack); |
3521 | } |
3522 | |
3523 | |
3524 | @@ -1547,10 +1733,7 @@ static int read_partial_message_section(struct ceph_connection *con, |
3525 | return 1; |
3526 | } |
3527 | |
3528 | -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, |
3529 | - struct ceph_msg_header *hdr, |
3530 | - int *skip); |
3531 | - |
3532 | +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip); |
3533 | |
3534 | static int read_partial_message_pages(struct ceph_connection *con, |
3535 | struct page **pages, |
3536 | @@ -1593,9 +1776,6 @@ static int read_partial_message_bio(struct ceph_connection *con, |
3537 | void *p; |
3538 | int ret, left; |
3539 | |
3540 | - if (IS_ERR(bv)) |
3541 | - return PTR_ERR(bv); |
3542 | - |
3543 | left = min((int)(data_len - con->in_msg_pos.data_pos), |
3544 | (int)(bv->bv_len - con->in_msg_pos.page_pos)); |
3545 | |
3546 | @@ -1627,26 +1807,22 @@ static int read_partial_message_bio(struct ceph_connection *con, |
3547 | static int read_partial_message(struct ceph_connection *con) |
3548 | { |
3549 | struct ceph_msg *m = con->in_msg; |
3550 | + int size; |
3551 | + int end; |
3552 | int ret; |
3553 | - int to, left; |
3554 | unsigned front_len, middle_len, data_len; |
3555 | bool do_datacrc = !con->msgr->nocrc; |
3556 | - int skip; |
3557 | u64 seq; |
3558 | u32 crc; |
3559 | |
3560 | dout("read_partial_message con %p msg %p\n", con, m); |
3561 | |
3562 | /* header */ |
3563 | - while (con->in_base_pos < sizeof(con->in_hdr)) { |
3564 | - left = sizeof(con->in_hdr) - con->in_base_pos; |
3565 | - ret = ceph_tcp_recvmsg(con->sock, |
3566 | - (char *)&con->in_hdr + con->in_base_pos, |
3567 | - left); |
3568 | - if (ret <= 0) |
3569 | - return ret; |
3570 | - con->in_base_pos += ret; |
3571 | - } |
3572 | + size = sizeof (con->in_hdr); |
3573 | + end = size; |
3574 | + ret = read_partial(con, end, size, &con->in_hdr); |
3575 | + if (ret <= 0) |
3576 | + return ret; |
3577 | |
3578 | crc = crc32c(0, &con->in_hdr, offsetof(struct ceph_msg_header, crc)); |
3579 | if (cpu_to_le32(crc) != con->in_hdr.crc) { |
3580 | @@ -1686,10 +1862,13 @@ static int read_partial_message(struct ceph_connection *con) |
3581 | |
3582 | /* allocate message? */ |
3583 | if (!con->in_msg) { |
3584 | + int skip = 0; |
3585 | + |
3586 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, |
3587 | con->in_hdr.front_len, con->in_hdr.data_len); |
3588 | - skip = 0; |
3589 | - con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); |
3590 | + ret = ceph_con_in_msg_alloc(con, &skip); |
3591 | + if (ret < 0) |
3592 | + return ret; |
3593 | if (skip) { |
3594 | /* skip this message */ |
3595 | dout("alloc_msg said skip message\n"); |
3596 | @@ -1700,11 +1879,9 @@ static int read_partial_message(struct ceph_connection *con) |
3597 | con->in_seq++; |
3598 | return 0; |
3599 | } |
3600 | - if (!con->in_msg) { |
3601 | - con->error_msg = |
3602 | - "error allocating memory for incoming message"; |
3603 | - return -ENOMEM; |
3604 | - } |
3605 | + |
3606 | + BUG_ON(!con->in_msg); |
3607 | + BUG_ON(con->in_msg->con != con); |
3608 | m = con->in_msg; |
3609 | m->front.iov_len = 0; /* haven't read it yet */ |
3610 | if (m->middle) |
3611 | @@ -1716,6 +1893,11 @@ static int read_partial_message(struct ceph_connection *con) |
3612 | else |
3613 | con->in_msg_pos.page_pos = 0; |
3614 | con->in_msg_pos.data_pos = 0; |
3615 | + |
3616 | +#ifdef CONFIG_BLOCK |
3617 | + if (m->bio) |
3618 | + init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); |
3619 | +#endif |
3620 | } |
3621 | |
3622 | /* front */ |
3623 | @@ -1732,10 +1914,6 @@ static int read_partial_message(struct ceph_connection *con) |
3624 | if (ret <= 0) |
3625 | return ret; |
3626 | } |
3627 | -#ifdef CONFIG_BLOCK |
3628 | - if (m->bio && !m->bio_iter) |
3629 | - init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); |
3630 | -#endif |
3631 | |
3632 | /* (page) data */ |
3633 | while (con->in_msg_pos.data_pos < data_len) { |
3634 | @@ -1746,7 +1924,7 @@ static int read_partial_message(struct ceph_connection *con) |
3635 | return ret; |
3636 | #ifdef CONFIG_BLOCK |
3637 | } else if (m->bio) { |
3638 | - |
3639 | + BUG_ON(!m->bio_iter); |
3640 | ret = read_partial_message_bio(con, |
3641 | &m->bio_iter, &m->bio_seg, |
3642 | data_len, do_datacrc); |
3643 | @@ -1759,16 +1937,12 @@ static int read_partial_message(struct ceph_connection *con) |
3644 | } |
3645 | |
3646 | /* footer */ |
3647 | - to = sizeof(m->hdr) + sizeof(m->footer); |
3648 | - while (con->in_base_pos < to) { |
3649 | - left = to - con->in_base_pos; |
3650 | - ret = ceph_tcp_recvmsg(con->sock, (char *)&m->footer + |
3651 | - (con->in_base_pos - sizeof(m->hdr)), |
3652 | - left); |
3653 | - if (ret <= 0) |
3654 | - return ret; |
3655 | - con->in_base_pos += ret; |
3656 | - } |
3657 | + size = sizeof (m->footer); |
3658 | + end += size; |
3659 | + ret = read_partial(con, end, size, &m->footer); |
3660 | + if (ret <= 0) |
3661 | + return ret; |
3662 | + |
3663 | dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n", |
3664 | m, front_len, m->footer.front_crc, middle_len, |
3665 | m->footer.middle_crc, data_len, m->footer.data_crc); |
3666 | @@ -1804,8 +1978,11 @@ static void process_message(struct ceph_connection *con) |
3667 | { |
3668 | struct ceph_msg *msg; |
3669 | |
3670 | + BUG_ON(con->in_msg->con != con); |
3671 | + con->in_msg->con = NULL; |
3672 | msg = con->in_msg; |
3673 | con->in_msg = NULL; |
3674 | + con->ops->put(con); |
3675 | |
3676 | /* if first message, set peer_name */ |
3677 | if (con->peer_name.type == 0) |
3678 | @@ -1825,7 +2002,6 @@ static void process_message(struct ceph_connection *con) |
3679 | con->ops->dispatch(con, msg); |
3680 | |
3681 | mutex_lock(&con->mutex); |
3682 | - prepare_read_tag(con); |
3683 | } |
3684 | |
3685 | |
3686 | @@ -1835,21 +2011,21 @@ static void process_message(struct ceph_connection *con) |
3687 | */ |
3688 | static int try_write(struct ceph_connection *con) |
3689 | { |
3690 | - struct ceph_messenger *msgr = con->msgr; |
3691 | int ret = 1; |
3692 | |
3693 | - dout("try_write start %p state %lu nref %d\n", con, con->state, |
3694 | - atomic_read(&con->nref)); |
3695 | + dout("try_write start %p state %lu\n", con, con->state); |
3696 | |
3697 | more: |
3698 | dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); |
3699 | |
3700 | /* open the socket first? */ |
3701 | - if (con->sock == NULL) { |
3702 | - prepare_write_connect(msgr, con, 1); |
3703 | + if (con->state == CON_STATE_PREOPEN) { |
3704 | + BUG_ON(con->sock); |
3705 | + con->state = CON_STATE_CONNECTING; |
3706 | + |
3707 | + con_out_kvec_reset(con); |
3708 | + prepare_write_banner(con); |
3709 | prepare_read_banner(con); |
3710 | - set_bit(CONNECTING, &con->state); |
3711 | - clear_bit(NEGOTIATING, &con->state); |
3712 | |
3713 | BUG_ON(con->in_msg); |
3714 | con->in_tag = CEPH_MSGR_TAG_READY; |
3715 | @@ -1896,7 +2072,7 @@ more_kvec: |
3716 | } |
3717 | |
3718 | do_next: |
3719 | - if (!test_bit(CONNECTING, &con->state)) { |
3720 | + if (con->state == CON_STATE_OPEN) { |
3721 | /* is anything else pending? */ |
3722 | if (!list_empty(&con->out_queue)) { |
3723 | prepare_write_message(con); |
3724 | @@ -1906,14 +2082,15 @@ do_next: |
3725 | prepare_write_ack(con); |
3726 | goto more; |
3727 | } |
3728 | - if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) { |
3729 | + if (test_and_clear_bit(CON_FLAG_KEEPALIVE_PENDING, |
3730 | + &con->flags)) { |
3731 | prepare_write_keepalive(con); |
3732 | goto more; |
3733 | } |
3734 | } |
3735 | |
3736 | /* Nothing to do! */ |
3737 | - clear_bit(WRITE_PENDING, &con->state); |
3738 | + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
3739 | dout("try_write nothing else to write.\n"); |
3740 | ret = 0; |
3741 | out: |
3742 | @@ -1930,38 +2107,46 @@ static int try_read(struct ceph_connection *con) |
3743 | { |
3744 | int ret = -1; |
3745 | |
3746 | - if (!con->sock) |
3747 | - return 0; |
3748 | - |
3749 | - if (test_bit(STANDBY, &con->state)) |
3750 | +more: |
3751 | + dout("try_read start on %p state %lu\n", con, con->state); |
3752 | + if (con->state != CON_STATE_CONNECTING && |
3753 | + con->state != CON_STATE_NEGOTIATING && |
3754 | + con->state != CON_STATE_OPEN) |
3755 | return 0; |
3756 | |
3757 | - dout("try_read start on %p\n", con); |
3758 | + BUG_ON(!con->sock); |
3759 | |
3760 | -more: |
3761 | dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag, |
3762 | con->in_base_pos); |
3763 | |
3764 | - /* |
3765 | - * process_connect and process_message drop and re-take |
3766 | - * con->mutex. make sure we handle a racing close or reopen. |
3767 | - */ |
3768 | - if (test_bit(CLOSED, &con->state) || |
3769 | - test_bit(OPENING, &con->state)) { |
3770 | - ret = -EAGAIN; |
3771 | + if (con->state == CON_STATE_CONNECTING) { |
3772 | + dout("try_read connecting\n"); |
3773 | + ret = read_partial_banner(con); |
3774 | + if (ret <= 0) |
3775 | + goto out; |
3776 | + ret = process_banner(con); |
3777 | + if (ret < 0) |
3778 | + goto out; |
3779 | + |
3780 | + BUG_ON(con->state != CON_STATE_CONNECTING); |
3781 | + con->state = CON_STATE_NEGOTIATING; |
3782 | + |
3783 | + /* |
3784 | + * Received banner is good, exchange connection info. |
3785 | + * Do not reset out_kvec, as sending our banner raced |
3786 | + * with receiving peer banner after connect completed. |
3787 | + */ |
3788 | + ret = prepare_write_connect(con); |
3789 | + if (ret < 0) |
3790 | + goto out; |
3791 | + prepare_read_connect(con); |
3792 | + |
3793 | + /* Send connection info before awaiting response */ |
3794 | goto out; |
3795 | } |
3796 | |
3797 | - if (test_bit(CONNECTING, &con->state)) { |
3798 | - if (!test_bit(NEGOTIATING, &con->state)) { |
3799 | - dout("try_read connecting\n"); |
3800 | - ret = read_partial_banner(con); |
3801 | - if (ret <= 0) |
3802 | - goto out; |
3803 | - ret = process_banner(con); |
3804 | - if (ret < 0) |
3805 | - goto out; |
3806 | - } |
3807 | + if (con->state == CON_STATE_NEGOTIATING) { |
3808 | + dout("try_read negotiating\n"); |
3809 | ret = read_partial_connect(con); |
3810 | if (ret <= 0) |
3811 | goto out; |
3812 | @@ -1971,6 +2156,8 @@ more: |
3813 | goto more; |
3814 | } |
3815 | |
3816 | + BUG_ON(con->state != CON_STATE_OPEN); |
3817 | + |
3818 | if (con->in_base_pos < 0) { |
3819 | /* |
3820 | * skipping + discarding content. |
3821 | @@ -2004,7 +2191,8 @@ more: |
3822 | prepare_read_ack(con); |
3823 | break; |
3824 | case CEPH_MSGR_TAG_CLOSE: |
3825 | - set_bit(CLOSED, &con->state); /* fixme */ |
3826 | + con_close_socket(con); |
3827 | + con->state = CON_STATE_CLOSED; |
3828 | goto out; |
3829 | default: |
3830 | goto bad_tag; |
3831 | @@ -2027,6 +2215,8 @@ more: |
3832 | if (con->in_tag == CEPH_MSGR_TAG_READY) |
3833 | goto more; |
3834 | process_message(con); |
3835 | + if (con->state == CON_STATE_OPEN) |
3836 | + prepare_read_tag(con); |
3837 | goto more; |
3838 | } |
3839 | if (con->in_tag == CEPH_MSGR_TAG_ACK) { |
3840 | @@ -2055,12 +2245,6 @@ bad_tag: |
3841 | */ |
3842 | static void queue_con(struct ceph_connection *con) |
3843 | { |
3844 | - if (test_bit(DEAD, &con->state)) { |
3845 | - dout("queue_con %p ignoring: DEAD\n", |
3846 | - con); |
3847 | - return; |
3848 | - } |
3849 | - |
3850 | if (!con->ops->get(con)) { |
3851 | dout("queue_con %p ref count 0\n", con); |
3852 | return; |
3853 | @@ -2085,7 +2269,26 @@ static void con_work(struct work_struct *work) |
3854 | |
3855 | mutex_lock(&con->mutex); |
3856 | restart: |
3857 | - if (test_and_clear_bit(BACKOFF, &con->state)) { |
3858 | + if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { |
3859 | + switch (con->state) { |
3860 | + case CON_STATE_CONNECTING: |
3861 | + con->error_msg = "connection failed"; |
3862 | + break; |
3863 | + case CON_STATE_NEGOTIATING: |
3864 | + con->error_msg = "negotiation failed"; |
3865 | + break; |
3866 | + case CON_STATE_OPEN: |
3867 | + con->error_msg = "socket closed"; |
3868 | + break; |
3869 | + default: |
3870 | + dout("unrecognized con state %d\n", (int)con->state); |
3871 | + con->error_msg = "unrecognized con state"; |
3872 | + BUG(); |
3873 | + } |
3874 | + goto fault; |
3875 | + } |
3876 | + |
3877 | + if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { |
3878 | dout("con_work %p backing off\n", con); |
3879 | if (queue_delayed_work(ceph_msgr_wq, &con->work, |
3880 | round_jiffies_relative(con->delay))) { |
3881 | @@ -2093,41 +2296,42 @@ restart: |
3882 | mutex_unlock(&con->mutex); |
3883 | return; |
3884 | } else { |
3885 | - con->ops->put(con); |
3886 | dout("con_work %p FAILED to back off %lu\n", con, |
3887 | con->delay); |
3888 | + set_bit(CON_FLAG_BACKOFF, &con->flags); |
3889 | } |
3890 | + goto done; |
3891 | } |
3892 | |
3893 | - if (test_bit(STANDBY, &con->state)) { |
3894 | + if (con->state == CON_STATE_STANDBY) { |
3895 | dout("con_work %p STANDBY\n", con); |
3896 | goto done; |
3897 | } |
3898 | - if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */ |
3899 | - dout("con_work CLOSED\n"); |
3900 | - con_close_socket(con); |
3901 | + if (con->state == CON_STATE_CLOSED) { |
3902 | + dout("con_work %p CLOSED\n", con); |
3903 | + BUG_ON(con->sock); |
3904 | goto done; |
3905 | } |
3906 | - if (test_and_clear_bit(OPENING, &con->state)) { |
3907 | - /* reopen w/ new peer */ |
3908 | + if (con->state == CON_STATE_PREOPEN) { |
3909 | dout("con_work OPENING\n"); |
3910 | - con_close_socket(con); |
3911 | + BUG_ON(con->sock); |
3912 | } |
3913 | |
3914 | - if (test_and_clear_bit(SOCK_CLOSED, &con->state)) |
3915 | - goto fault; |
3916 | - |
3917 | ret = try_read(con); |
3918 | if (ret == -EAGAIN) |
3919 | goto restart; |
3920 | - if (ret < 0) |
3921 | + if (ret < 0) { |
3922 | + con->error_msg = "socket error on read"; |
3923 | goto fault; |
3924 | + } |
3925 | |
3926 | ret = try_write(con); |
3927 | if (ret == -EAGAIN) |
3928 | goto restart; |
3929 | - if (ret < 0) |
3930 | + if (ret < 0) { |
3931 | + con->error_msg = "socket error on write"; |
3932 | goto fault; |
3933 | + } |
3934 | |
3935 | done: |
3936 | mutex_unlock(&con->mutex); |
3937 | @@ -2136,7 +2340,6 @@ done_unlocked: |
3938 | return; |
3939 | |
3940 | fault: |
3941 | - mutex_unlock(&con->mutex); |
3942 | ceph_fault(con); /* error/fault path */ |
3943 | goto done_unlocked; |
3944 | } |
3945 | @@ -2147,26 +2350,31 @@ fault: |
3946 | * exponential backoff |
3947 | */ |
3948 | static void ceph_fault(struct ceph_connection *con) |
3949 | + __releases(con->mutex) |
3950 | { |
3951 | pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), |
3952 | ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); |
3953 | dout("fault %p state %lu to peer %s\n", |
3954 | con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); |
3955 | |
3956 | - if (test_bit(LOSSYTX, &con->state)) { |
3957 | - dout("fault on LOSSYTX channel\n"); |
3958 | - goto out; |
3959 | - } |
3960 | - |
3961 | - mutex_lock(&con->mutex); |
3962 | - if (test_bit(CLOSED, &con->state)) |
3963 | - goto out_unlock; |
3964 | + BUG_ON(con->state != CON_STATE_CONNECTING && |
3965 | + con->state != CON_STATE_NEGOTIATING && |
3966 | + con->state != CON_STATE_OPEN); |
3967 | |
3968 | con_close_socket(con); |
3969 | |
3970 | + if (test_bit(CON_FLAG_LOSSYTX, &con->flags)) { |
3971 | + dout("fault on LOSSYTX channel, marking CLOSED\n"); |
3972 | + con->state = CON_STATE_CLOSED; |
3973 | + goto out_unlock; |
3974 | + } |
3975 | + |
3976 | if (con->in_msg) { |
3977 | + BUG_ON(con->in_msg->con != con); |
3978 | + con->in_msg->con = NULL; |
3979 | ceph_msg_put(con->in_msg); |
3980 | con->in_msg = NULL; |
3981 | + con->ops->put(con); |
3982 | } |
3983 | |
3984 | /* Requeue anything that hasn't been acked */ |
3985 | @@ -2175,12 +2383,13 @@ static void ceph_fault(struct ceph_connection *con) |
3986 | /* If there are no messages queued or keepalive pending, place |
3987 | * the connection in a STANDBY state */ |
3988 | if (list_empty(&con->out_queue) && |
3989 | - !test_bit(KEEPALIVE_PENDING, &con->state)) { |
3990 | + !test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)) { |
3991 | dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); |
3992 | - clear_bit(WRITE_PENDING, &con->state); |
3993 | - set_bit(STANDBY, &con->state); |
3994 | + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); |
3995 | + con->state = CON_STATE_STANDBY; |
3996 | } else { |
3997 | /* retry after a delay. */ |
3998 | + con->state = CON_STATE_PREOPEN; |
3999 | if (con->delay == 0) |
4000 | con->delay = BASE_DELAY_INTERVAL; |
4001 | else if (con->delay < MAX_DELAY_INTERVAL) |
4002 | @@ -2201,13 +2410,12 @@ static void ceph_fault(struct ceph_connection *con) |
4003 | * that when con_work restarts we schedule the |
4004 | * delay then. |
4005 | */ |
4006 | - set_bit(BACKOFF, &con->state); |
4007 | + set_bit(CON_FLAG_BACKOFF, &con->flags); |
4008 | } |
4009 | } |
4010 | |
4011 | out_unlock: |
4012 | mutex_unlock(&con->mutex); |
4013 | -out: |
4014 | /* |
4015 | * in case we faulted due to authentication, invalidate our |
4016 | * current tickets so that we can get new ones. |
4017 | @@ -2224,18 +2432,14 @@ out: |
4018 | |
4019 | |
4020 | /* |
4021 | - * create a new messenger instance |
4022 | + * initialize a new messenger instance |
4023 | */ |
4024 | -struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, |
4025 | - u32 supported_features, |
4026 | - u32 required_features) |
4027 | +void ceph_messenger_init(struct ceph_messenger *msgr, |
4028 | + struct ceph_entity_addr *myaddr, |
4029 | + u32 supported_features, |
4030 | + u32 required_features, |
4031 | + bool nocrc) |
4032 | { |
4033 | - struct ceph_messenger *msgr; |
4034 | - |
4035 | - msgr = kzalloc(sizeof(*msgr), GFP_KERNEL); |
4036 | - if (msgr == NULL) |
4037 | - return ERR_PTR(-ENOMEM); |
4038 | - |
4039 | msgr->supported_features = supported_features; |
4040 | msgr->required_features = required_features; |
4041 | |
4042 | @@ -2248,30 +2452,23 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, |
4043 | msgr->inst.addr.type = 0; |
4044 | get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce)); |
4045 | encode_my_addr(msgr); |
4046 | + msgr->nocrc = nocrc; |
4047 | |
4048 | - dout("messenger_create %p\n", msgr); |
4049 | - return msgr; |
4050 | -} |
4051 | -EXPORT_SYMBOL(ceph_messenger_create); |
4052 | + atomic_set(&msgr->stopping, 0); |
4053 | |
4054 | -void ceph_messenger_destroy(struct ceph_messenger *msgr) |
4055 | -{ |
4056 | - dout("destroy %p\n", msgr); |
4057 | - kfree(msgr); |
4058 | - dout("destroyed messenger %p\n", msgr); |
4059 | + dout("%s %p\n", __func__, msgr); |
4060 | } |
4061 | -EXPORT_SYMBOL(ceph_messenger_destroy); |
4062 | +EXPORT_SYMBOL(ceph_messenger_init); |
4063 | |
4064 | static void clear_standby(struct ceph_connection *con) |
4065 | { |
4066 | /* come back from STANDBY? */ |
4067 | - if (test_and_clear_bit(STANDBY, &con->state)) { |
4068 | - mutex_lock(&con->mutex); |
4069 | + if (con->state == CON_STATE_STANDBY) { |
4070 | dout("clear_standby %p and ++connect_seq\n", con); |
4071 | + con->state = CON_STATE_PREOPEN; |
4072 | con->connect_seq++; |
4073 | - WARN_ON(test_bit(WRITE_PENDING, &con->state)); |
4074 | - WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state)); |
4075 | - mutex_unlock(&con->mutex); |
4076 | + WARN_ON(test_bit(CON_FLAG_WRITE_PENDING, &con->flags)); |
4077 | + WARN_ON(test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)); |
4078 | } |
4079 | } |
4080 | |
4081 | @@ -2280,21 +2477,24 @@ static void clear_standby(struct ceph_connection *con) |
4082 | */ |
4083 | void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) |
4084 | { |
4085 | - if (test_bit(CLOSED, &con->state)) { |
4086 | - dout("con_send %p closed, dropping %p\n", con, msg); |
4087 | - ceph_msg_put(msg); |
4088 | - return; |
4089 | - } |
4090 | - |
4091 | /* set src+dst */ |
4092 | msg->hdr.src = con->msgr->inst.name; |
4093 | - |
4094 | BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len)); |
4095 | - |
4096 | msg->needs_out_seq = true; |
4097 | |
4098 | - /* queue */ |
4099 | mutex_lock(&con->mutex); |
4100 | + |
4101 | + if (con->state == CON_STATE_CLOSED) { |
4102 | + dout("con_send %p closed, dropping %p\n", con, msg); |
4103 | + ceph_msg_put(msg); |
4104 | + mutex_unlock(&con->mutex); |
4105 | + return; |
4106 | + } |
4107 | + |
4108 | + BUG_ON(msg->con != NULL); |
4109 | + msg->con = con->ops->get(con); |
4110 | + BUG_ON(msg->con == NULL); |
4111 | + |
4112 | BUG_ON(!list_empty(&msg->list_head)); |
4113 | list_add_tail(&msg->list_head, &con->out_queue); |
4114 | dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg, |
4115 | @@ -2303,12 +2503,13 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) |
4116 | le32_to_cpu(msg->hdr.front_len), |
4117 | le32_to_cpu(msg->hdr.middle_len), |
4118 | le32_to_cpu(msg->hdr.data_len)); |
4119 | + |
4120 | + clear_standby(con); |
4121 | mutex_unlock(&con->mutex); |
4122 | |
4123 | /* if there wasn't anything waiting to send before, queue |
4124 | * new work */ |
4125 | - clear_standby(con); |
4126 | - if (test_and_set_bit(WRITE_PENDING, &con->state) == 0) |
4127 | + if (test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) |
4128 | queue_con(con); |
4129 | } |
4130 | EXPORT_SYMBOL(ceph_con_send); |
4131 | @@ -2316,24 +2517,34 @@ EXPORT_SYMBOL(ceph_con_send); |
4132 | /* |
4133 | * Revoke a message that was previously queued for send |
4134 | */ |
4135 | -void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) |
4136 | +void ceph_msg_revoke(struct ceph_msg *msg) |
4137 | { |
4138 | + struct ceph_connection *con = msg->con; |
4139 | + |
4140 | + if (!con) |
4141 | + return; /* Message not in our possession */ |
4142 | + |
4143 | mutex_lock(&con->mutex); |
4144 | if (!list_empty(&msg->list_head)) { |
4145 | - dout("con_revoke %p msg %p - was on queue\n", con, msg); |
4146 | + dout("%s %p msg %p - was on queue\n", __func__, con, msg); |
4147 | list_del_init(&msg->list_head); |
4148 | - ceph_msg_put(msg); |
4149 | + BUG_ON(msg->con == NULL); |
4150 | + msg->con->ops->put(msg->con); |
4151 | + msg->con = NULL; |
4152 | msg->hdr.seq = 0; |
4153 | + |
4154 | + ceph_msg_put(msg); |
4155 | } |
4156 | if (con->out_msg == msg) { |
4157 | - dout("con_revoke %p msg %p - was sending\n", con, msg); |
4158 | + dout("%s %p msg %p - was sending\n", __func__, con, msg); |
4159 | con->out_msg = NULL; |
4160 | if (con->out_kvec_is_msg) { |
4161 | con->out_skip = con->out_kvec_bytes; |
4162 | con->out_kvec_is_msg = false; |
4163 | } |
4164 | - ceph_msg_put(msg); |
4165 | msg->hdr.seq = 0; |
4166 | + |
4167 | + ceph_msg_put(msg); |
4168 | } |
4169 | mutex_unlock(&con->mutex); |
4170 | } |
4171 | @@ -2341,17 +2552,27 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) |
4172 | /* |
4173 | * Revoke a message that we may be reading data into |
4174 | */ |
4175 | -void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) |
4176 | +void ceph_msg_revoke_incoming(struct ceph_msg *msg) |
4177 | { |
4178 | + struct ceph_connection *con; |
4179 | + |
4180 | + BUG_ON(msg == NULL); |
4181 | + if (!msg->con) { |
4182 | + dout("%s msg %p null con\n", __func__, msg); |
4183 | + |
4184 | + return; /* Message not in our possession */ |
4185 | + } |
4186 | + |
4187 | + con = msg->con; |
4188 | mutex_lock(&con->mutex); |
4189 | - if (con->in_msg && con->in_msg == msg) { |
4190 | + if (con->in_msg == msg) { |
4191 | unsigned front_len = le32_to_cpu(con->in_hdr.front_len); |
4192 | unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len); |
4193 | unsigned data_len = le32_to_cpu(con->in_hdr.data_len); |
4194 | |
4195 | /* skip rest of message */ |
4196 | - dout("con_revoke_pages %p msg %p revoked\n", con, msg); |
4197 | - con->in_base_pos = con->in_base_pos - |
4198 | + dout("%s %p msg %p revoked\n", __func__, con, msg); |
4199 | + con->in_base_pos = con->in_base_pos - |
4200 | sizeof(struct ceph_msg_header) - |
4201 | front_len - |
4202 | middle_len - |
4203 | @@ -2362,8 +2583,8 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) |
4204 | con->in_tag = CEPH_MSGR_TAG_READY; |
4205 | con->in_seq++; |
4206 | } else { |
4207 | - dout("con_revoke_pages %p msg %p pages %p no-op\n", |
4208 | - con, con->in_msg, msg); |
4209 | + dout("%s %p in_msg %p msg %p no-op\n", |
4210 | + __func__, con, con->in_msg, msg); |
4211 | } |
4212 | mutex_unlock(&con->mutex); |
4213 | } |
4214 | @@ -2374,9 +2595,11 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) |
4215 | void ceph_con_keepalive(struct ceph_connection *con) |
4216 | { |
4217 | dout("con_keepalive %p\n", con); |
4218 | + mutex_lock(&con->mutex); |
4219 | clear_standby(con); |
4220 | - if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 && |
4221 | - test_and_set_bit(WRITE_PENDING, &con->state) == 0) |
4222 | + mutex_unlock(&con->mutex); |
4223 | + if (test_and_set_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags) == 0 && |
4224 | + test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) |
4225 | queue_con(con); |
4226 | } |
4227 | EXPORT_SYMBOL(ceph_con_keepalive); |
4228 | @@ -2395,6 +2618,8 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, |
4229 | if (m == NULL) |
4230 | goto out; |
4231 | kref_init(&m->kref); |
4232 | + |
4233 | + m->con = NULL; |
4234 | INIT_LIST_HEAD(&m->list_head); |
4235 | |
4236 | m->hdr.tid = 0; |
4237 | @@ -2490,46 +2715,78 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) |
4238 | } |
4239 | |
4240 | /* |
4241 | - * Generic message allocator, for incoming messages. |
4242 | + * Allocate a message for receiving an incoming message on a |
4243 | + * connection, and save the result in con->in_msg. Uses the |
4244 | + * connection's private alloc_msg op if available. |
4245 | + * |
4246 | + * Returns 0 on success, or a negative error code. |
4247 | + * |
4248 | + * On success, if we set *skip = 1: |
4249 | + * - the next message should be skipped and ignored. |
4250 | + * - con->in_msg == NULL |
4251 | + * or if we set *skip = 0: |
4252 | + * - con->in_msg is non-null. |
4253 | + * On error (ENOMEM, EAGAIN, ...), |
4254 | + * - con->in_msg == NULL |
4255 | */ |
4256 | -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, |
4257 | - struct ceph_msg_header *hdr, |
4258 | - int *skip) |
4259 | +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) |
4260 | { |
4261 | + struct ceph_msg_header *hdr = &con->in_hdr; |
4262 | int type = le16_to_cpu(hdr->type); |
4263 | int front_len = le32_to_cpu(hdr->front_len); |
4264 | int middle_len = le32_to_cpu(hdr->middle_len); |
4265 | - struct ceph_msg *msg = NULL; |
4266 | - int ret; |
4267 | + int ret = 0; |
4268 | + |
4269 | + BUG_ON(con->in_msg != NULL); |
4270 | |
4271 | if (con->ops->alloc_msg) { |
4272 | + struct ceph_msg *msg; |
4273 | + |
4274 | mutex_unlock(&con->mutex); |
4275 | msg = con->ops->alloc_msg(con, hdr, skip); |
4276 | mutex_lock(&con->mutex); |
4277 | - if (!msg || *skip) |
4278 | - return NULL; |
4279 | + if (con->state != CON_STATE_OPEN) { |
4280 | + if (msg) |
4281 | + ceph_msg_put(msg); |
4282 | + return -EAGAIN; |
4283 | + } |
4284 | + con->in_msg = msg; |
4285 | + if (con->in_msg) { |
4286 | + con->in_msg->con = con->ops->get(con); |
4287 | + BUG_ON(con->in_msg->con == NULL); |
4288 | + } |
4289 | + if (*skip) { |
4290 | + con->in_msg = NULL; |
4291 | + return 0; |
4292 | + } |
4293 | + if (!con->in_msg) { |
4294 | + con->error_msg = |
4295 | + "error allocating memory for incoming message"; |
4296 | + return -ENOMEM; |
4297 | + } |
4298 | } |
4299 | - if (!msg) { |
4300 | - *skip = 0; |
4301 | - msg = ceph_msg_new(type, front_len, GFP_NOFS, false); |
4302 | - if (!msg) { |
4303 | + if (!con->in_msg) { |
4304 | + con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false); |
4305 | + if (!con->in_msg) { |
4306 | pr_err("unable to allocate msg type %d len %d\n", |
4307 | type, front_len); |
4308 | - return NULL; |
4309 | + return -ENOMEM; |
4310 | } |
4311 | - msg->page_alignment = le16_to_cpu(hdr->data_off); |
4312 | + con->in_msg->con = con->ops->get(con); |
4313 | + BUG_ON(con->in_msg->con == NULL); |
4314 | + con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); |
4315 | } |
4316 | - memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); |
4317 | + memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); |
4318 | |
4319 | - if (middle_len && !msg->middle) { |
4320 | - ret = ceph_alloc_middle(con, msg); |
4321 | + if (middle_len && !con->in_msg->middle) { |
4322 | + ret = ceph_alloc_middle(con, con->in_msg); |
4323 | if (ret < 0) { |
4324 | - ceph_msg_put(msg); |
4325 | - return NULL; |
4326 | + ceph_msg_put(con->in_msg); |
4327 | + con->in_msg = NULL; |
4328 | } |
4329 | } |
4330 | |
4331 | - return msg; |
4332 | + return ret; |
4333 | } |
4334 | |
4335 | |
4336 | diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c |
4337 | index 1845cde..89a6409 100644 |
4338 | --- a/net/ceph/mon_client.c |
4339 | +++ b/net/ceph/mon_client.c |
4340 | @@ -106,9 +106,9 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) |
4341 | monc->pending_auth = 1; |
4342 | monc->m_auth->front.iov_len = len; |
4343 | monc->m_auth->hdr.front_len = cpu_to_le32(len); |
4344 | - ceph_con_revoke(monc->con, monc->m_auth); |
4345 | + ceph_msg_revoke(monc->m_auth); |
4346 | ceph_msg_get(monc->m_auth); /* keep our ref */ |
4347 | - ceph_con_send(monc->con, monc->m_auth); |
4348 | + ceph_con_send(&monc->con, monc->m_auth); |
4349 | } |
4350 | |
4351 | /* |
4352 | @@ -117,8 +117,11 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) |
4353 | static void __close_session(struct ceph_mon_client *monc) |
4354 | { |
4355 | dout("__close_session closing mon%d\n", monc->cur_mon); |
4356 | - ceph_con_revoke(monc->con, monc->m_auth); |
4357 | - ceph_con_close(monc->con); |
4358 | + ceph_msg_revoke(monc->m_auth); |
4359 | + ceph_msg_revoke_incoming(monc->m_auth_reply); |
4360 | + ceph_msg_revoke(monc->m_subscribe); |
4361 | + ceph_msg_revoke_incoming(monc->m_subscribe_ack); |
4362 | + ceph_con_close(&monc->con); |
4363 | monc->cur_mon = -1; |
4364 | monc->pending_auth = 0; |
4365 | ceph_auth_reset(monc->auth); |
4366 | @@ -142,9 +145,8 @@ static int __open_session(struct ceph_mon_client *monc) |
4367 | monc->want_next_osdmap = !!monc->want_next_osdmap; |
4368 | |
4369 | dout("open_session mon%d opening\n", monc->cur_mon); |
4370 | - monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON; |
4371 | - monc->con->peer_name.num = cpu_to_le64(monc->cur_mon); |
4372 | - ceph_con_open(monc->con, |
4373 | + ceph_con_open(&monc->con, |
4374 | + CEPH_ENTITY_TYPE_MON, monc->cur_mon, |
4375 | &monc->monmap->mon_inst[monc->cur_mon].addr); |
4376 | |
4377 | /* initiatiate authentication handshake */ |
4378 | @@ -226,8 +228,8 @@ static void __send_subscribe(struct ceph_mon_client *monc) |
4379 | |
4380 | msg->front.iov_len = p - msg->front.iov_base; |
4381 | msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); |
4382 | - ceph_con_revoke(monc->con, msg); |
4383 | - ceph_con_send(monc->con, ceph_msg_get(msg)); |
4384 | + ceph_msg_revoke(msg); |
4385 | + ceph_con_send(&monc->con, ceph_msg_get(msg)); |
4386 | |
4387 | monc->sub_sent = jiffies | 1; /* never 0 */ |
4388 | } |
4389 | @@ -247,7 +249,7 @@ static void handle_subscribe_ack(struct ceph_mon_client *monc, |
4390 | if (monc->hunting) { |
4391 | pr_info("mon%d %s session established\n", |
4392 | monc->cur_mon, |
4393 | - ceph_pr_addr(&monc->con->peer_addr.in_addr)); |
4394 | + ceph_pr_addr(&monc->con.peer_addr.in_addr)); |
4395 | monc->hunting = false; |
4396 | } |
4397 | dout("handle_subscribe_ack after %d seconds\n", seconds); |
4398 | @@ -309,6 +311,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) |
4399 | EXPORT_SYMBOL(ceph_monc_open_session); |
4400 | |
4401 | /* |
4402 | + * We require the fsid and global_id in order to initialize our |
4403 | + * debugfs dir. |
4404 | + */ |
4405 | +static bool have_debugfs_info(struct ceph_mon_client *monc) |
4406 | +{ |
4407 | + dout("have_debugfs_info fsid %d globalid %lld\n", |
4408 | + (int)monc->client->have_fsid, monc->auth->global_id); |
4409 | + return monc->client->have_fsid && monc->auth->global_id > 0; |
4410 | +} |
4411 | + |
4412 | +/* |
4413 | * The monitor responds with mount ack indicate mount success. The |
4414 | * included client ticket allows the client to talk to MDSs and OSDs. |
4415 | */ |
4416 | @@ -318,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, |
4417 | struct ceph_client *client = monc->client; |
4418 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; |
4419 | void *p, *end; |
4420 | + int had_debugfs_info, init_debugfs = 0; |
4421 | |
4422 | mutex_lock(&monc->mutex); |
4423 | |
4424 | + had_debugfs_info = have_debugfs_info(monc); |
4425 | + |
4426 | dout("handle_monmap\n"); |
4427 | p = msg->front.iov_base; |
4428 | end = p + msg->front.iov_len; |
4429 | @@ -342,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, |
4430 | |
4431 | if (!client->have_fsid) { |
4432 | client->have_fsid = true; |
4433 | + if (!had_debugfs_info && have_debugfs_info(monc)) { |
4434 | + pr_info("client%lld fsid %pU\n", |
4435 | + ceph_client_id(monc->client), |
4436 | + &monc->client->fsid); |
4437 | + init_debugfs = 1; |
4438 | + } |
4439 | mutex_unlock(&monc->mutex); |
4440 | - /* |
4441 | - * do debugfs initialization without mutex to avoid |
4442 | - * creating a locking dependency |
4443 | - */ |
4444 | - ceph_debugfs_client_init(client); |
4445 | + |
4446 | + if (init_debugfs) { |
4447 | + /* |
4448 | + * do debugfs initialization without mutex to avoid |
4449 | + * creating a locking dependency |
4450 | + */ |
4451 | + ceph_debugfs_client_init(monc->client); |
4452 | + } |
4453 | + |
4454 | goto out_unlocked; |
4455 | } |
4456 | out: |
4457 | @@ -439,6 +465,7 @@ static struct ceph_msg *get_generic_reply(struct ceph_connection *con, |
4458 | m = NULL; |
4459 | } else { |
4460 | dout("get_generic_reply %lld got %p\n", tid, req->reply); |
4461 | + *skip = 0; |
4462 | m = ceph_msg_get(req->reply); |
4463 | /* |
4464 | * we don't need to track the connection reading into |
4465 | @@ -461,7 +488,7 @@ static int do_generic_request(struct ceph_mon_client *monc, |
4466 | req->request->hdr.tid = cpu_to_le64(req->tid); |
4467 | __insert_generic_request(monc, req); |
4468 | monc->num_generic_requests++; |
4469 | - ceph_con_send(monc->con, ceph_msg_get(req->request)); |
4470 | + ceph_con_send(&monc->con, ceph_msg_get(req->request)); |
4471 | mutex_unlock(&monc->mutex); |
4472 | |
4473 | err = wait_for_completion_interruptible(&req->completion); |
4474 | @@ -684,8 +711,9 @@ static void __resend_generic_request(struct ceph_mon_client *monc) |
4475 | |
4476 | for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { |
4477 | req = rb_entry(p, struct ceph_mon_generic_request, node); |
4478 | - ceph_con_revoke(monc->con, req->request); |
4479 | - ceph_con_send(monc->con, ceph_msg_get(req->request)); |
4480 | + ceph_msg_revoke(req->request); |
4481 | + ceph_msg_revoke_incoming(req->reply); |
4482 | + ceph_con_send(&monc->con, ceph_msg_get(req->request)); |
4483 | } |
4484 | } |
4485 | |
4486 | @@ -705,7 +733,7 @@ static void delayed_work(struct work_struct *work) |
4487 | __close_session(monc); |
4488 | __open_session(monc); /* continue hunting */ |
4489 | } else { |
4490 | - ceph_con_keepalive(monc->con); |
4491 | + ceph_con_keepalive(&monc->con); |
4492 | |
4493 | __validate_auth(monc); |
4494 | |
4495 | @@ -760,19 +788,12 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) |
4496 | goto out; |
4497 | |
4498 | /* connection */ |
4499 | - monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); |
4500 | - if (!monc->con) |
4501 | - goto out_monmap; |
4502 | - ceph_con_init(monc->client->msgr, monc->con); |
4503 | - monc->con->private = monc; |
4504 | - monc->con->ops = &mon_con_ops; |
4505 | - |
4506 | /* authentication */ |
4507 | monc->auth = ceph_auth_init(cl->options->name, |
4508 | cl->options->key); |
4509 | if (IS_ERR(monc->auth)) { |
4510 | err = PTR_ERR(monc->auth); |
4511 | - goto out_con; |
4512 | + goto out_monmap; |
4513 | } |
4514 | monc->auth->want_keys = |
4515 | CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON | |
4516 | @@ -801,6 +822,9 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) |
4517 | if (!monc->m_auth) |
4518 | goto out_auth_reply; |
4519 | |
4520 | + ceph_con_init(&monc->con, monc, &mon_con_ops, |
4521 | + &monc->client->msgr); |
4522 | + |
4523 | monc->cur_mon = -1; |
4524 | monc->hunting = true; |
4525 | monc->sub_renew_after = jiffies; |
4526 | @@ -824,8 +848,6 @@ out_subscribe_ack: |
4527 | ceph_msg_put(monc->m_subscribe_ack); |
4528 | out_auth: |
4529 | ceph_auth_destroy(monc->auth); |
4530 | -out_con: |
4531 | - monc->con->ops->put(monc->con); |
4532 | out_monmap: |
4533 | kfree(monc->monmap); |
4534 | out: |
4535 | @@ -841,12 +863,16 @@ void ceph_monc_stop(struct ceph_mon_client *monc) |
4536 | mutex_lock(&monc->mutex); |
4537 | __close_session(monc); |
4538 | |
4539 | - monc->con->private = NULL; |
4540 | - monc->con->ops->put(monc->con); |
4541 | - monc->con = NULL; |
4542 | - |
4543 | mutex_unlock(&monc->mutex); |
4544 | |
4545 | + /* |
4546 | + * flush msgr queue before we destroy ourselves to ensure that: |
4547 | + * - any work that references our embedded con is finished. |
4548 | + * - any osd_client or other work that may reference an authorizer |
4549 | + * finishes before we shut down the auth subsystem. |
4550 | + */ |
4551 | + ceph_msgr_flush(); |
4552 | + |
4553 | ceph_auth_destroy(monc->auth); |
4554 | |
4555 | ceph_msg_put(monc->m_auth); |
4556 | @@ -863,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, |
4557 | { |
4558 | int ret; |
4559 | int was_auth = 0; |
4560 | + int had_debugfs_info, init_debugfs = 0; |
4561 | |
4562 | mutex_lock(&monc->mutex); |
4563 | + had_debugfs_info = have_debugfs_info(monc); |
4564 | if (monc->auth->ops) |
4565 | was_auth = monc->auth->ops->is_authenticated(monc->auth); |
4566 | monc->pending_auth = 0; |
4567 | @@ -880,14 +908,29 @@ static void handle_auth_reply(struct ceph_mon_client *monc, |
4568 | } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { |
4569 | dout("authenticated, starting session\n"); |
4570 | |
4571 | - monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; |
4572 | - monc->client->msgr->inst.name.num = |
4573 | + monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT; |
4574 | + monc->client->msgr.inst.name.num = |
4575 | cpu_to_le64(monc->auth->global_id); |
4576 | |
4577 | __send_subscribe(monc); |
4578 | __resend_generic_request(monc); |
4579 | } |
4580 | + |
4581 | + if (!had_debugfs_info && have_debugfs_info(monc)) { |
4582 | + pr_info("client%lld fsid %pU\n", |
4583 | + ceph_client_id(monc->client), |
4584 | + &monc->client->fsid); |
4585 | + init_debugfs = 1; |
4586 | + } |
4587 | mutex_unlock(&monc->mutex); |
4588 | + |
4589 | + if (init_debugfs) { |
4590 | + /* |
4591 | + * do debugfs initialization without mutex to avoid |
4592 | + * creating a locking dependency |
4593 | + */ |
4594 | + ceph_debugfs_client_init(monc->client); |
4595 | + } |
4596 | } |
4597 | |
4598 | static int __validate_auth(struct ceph_mon_client *monc) |
4599 | @@ -992,6 +1035,8 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, |
4600 | case CEPH_MSG_MDS_MAP: |
4601 | case CEPH_MSG_OSD_MAP: |
4602 | m = ceph_msg_new(type, front_len, GFP_NOFS, false); |
4603 | + if (!m) |
4604 | + return NULL; /* ENOMEM--return skip == 0 */ |
4605 | break; |
4606 | } |
4607 | |
4608 | @@ -1021,7 +1066,7 @@ static void mon_fault(struct ceph_connection *con) |
4609 | if (!monc->hunting) |
4610 | pr_info("mon%d %s session lost, " |
4611 | "hunting for new mon\n", monc->cur_mon, |
4612 | - ceph_pr_addr(&monc->con->peer_addr.in_addr)); |
4613 | + ceph_pr_addr(&monc->con.peer_addr.in_addr)); |
4614 | |
4615 | __close_session(monc); |
4616 | if (!monc->hunting) { |
4617 | @@ -1036,9 +1081,23 @@ out: |
4618 | mutex_unlock(&monc->mutex); |
4619 | } |
4620 | |
4621 | +/* |
4622 | + * We can ignore refcounting on the connection struct, as all references |
4623 | + * will come from the messenger workqueue, which is drained prior to |
4624 | + * mon_client destruction. |
4625 | + */ |
4626 | +static struct ceph_connection *con_get(struct ceph_connection *con) |
4627 | +{ |
4628 | + return con; |
4629 | +} |
4630 | + |
4631 | +static void con_put(struct ceph_connection *con) |
4632 | +{ |
4633 | +} |
4634 | + |
4635 | static const struct ceph_connection_operations mon_con_ops = { |
4636 | - .get = ceph_con_get, |
4637 | - .put = ceph_con_put, |
4638 | + .get = con_get, |
4639 | + .put = con_put, |
4640 | .dispatch = dispatch, |
4641 | .fault = mon_fault, |
4642 | .alloc_msg = mon_alloc_msg, |
4643 | diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c |
4644 | index 11d5f41..ddec1c1 100644 |
4645 | --- a/net/ceph/msgpool.c |
4646 | +++ b/net/ceph/msgpool.c |
4647 | @@ -12,7 +12,7 @@ static void *msgpool_alloc(gfp_t gfp_mask, void *arg) |
4648 | struct ceph_msgpool *pool = arg; |
4649 | struct ceph_msg *msg; |
4650 | |
4651 | - msg = ceph_msg_new(0, pool->front_len, gfp_mask, true); |
4652 | + msg = ceph_msg_new(pool->type, pool->front_len, gfp_mask, true); |
4653 | if (!msg) { |
4654 | dout("msgpool_alloc %s failed\n", pool->name); |
4655 | } else { |
4656 | @@ -32,10 +32,11 @@ static void msgpool_free(void *element, void *arg) |
4657 | ceph_msg_put(msg); |
4658 | } |
4659 | |
4660 | -int ceph_msgpool_init(struct ceph_msgpool *pool, |
4661 | +int ceph_msgpool_init(struct ceph_msgpool *pool, int type, |
4662 | int front_len, int size, bool blocking, const char *name) |
4663 | { |
4664 | dout("msgpool %s init\n", name); |
4665 | + pool->type = type; |
4666 | pool->front_len = front_len; |
4667 | pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool); |
4668 | if (!pool->pool) |
4669 | @@ -61,7 +62,7 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, |
4670 | WARN_ON(1); |
4671 | |
4672 | /* try to alloc a fresh message */ |
4673 | - return ceph_msg_new(0, front_len, GFP_NOFS, false); |
4674 | + return ceph_msg_new(pool->type, front_len, GFP_NOFS, false); |
4675 | } |
4676 | |
4677 | msg = mempool_alloc(pool->pool, GFP_NOFS); |
4678 | diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c |
4679 | index 5e25405..a79dbae 100644 |
4680 | --- a/net/ceph/osd_client.c |
4681 | +++ b/net/ceph/osd_client.c |
4682 | @@ -52,7 +52,7 @@ static int op_has_extent(int op) |
4683 | op == CEPH_OSD_OP_WRITE); |
4684 | } |
4685 | |
4686 | -void ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
4687 | +int ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
4688 | struct ceph_file_layout *layout, |
4689 | u64 snapid, |
4690 | u64 off, u64 *plen, u64 *bno, |
4691 | @@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
4692 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; |
4693 | u64 orig_len = *plen; |
4694 | u64 objoff, objlen; /* extent in object */ |
4695 | + int r; |
4696 | |
4697 | reqhead->snapid = cpu_to_le64(snapid); |
4698 | |
4699 | /* object extent? */ |
4700 | - ceph_calc_file_object_mapping(layout, off, plen, bno, |
4701 | - &objoff, &objlen); |
4702 | + r = ceph_calc_file_object_mapping(layout, off, plen, bno, |
4703 | + &objoff, &objlen); |
4704 | + if (r < 0) |
4705 | + return r; |
4706 | if (*plen < orig_len) |
4707 | dout(" skipping last %llu, final file extent %llu~%llu\n", |
4708 | orig_len - *plen, off, *plen); |
4709 | @@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
4710 | |
4711 | dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", |
4712 | *bno, objoff, objlen, req->r_num_pages); |
4713 | - |
4714 | + return 0; |
4715 | } |
4716 | EXPORT_SYMBOL(ceph_calc_raw_layout); |
4717 | |
4718 | @@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout); |
4719 | * |
4720 | * fill osd op in request message. |
4721 | */ |
4722 | -static void calc_layout(struct ceph_osd_client *osdc, |
4723 | - struct ceph_vino vino, |
4724 | - struct ceph_file_layout *layout, |
4725 | - u64 off, u64 *plen, |
4726 | - struct ceph_osd_request *req, |
4727 | - struct ceph_osd_req_op *op) |
4728 | +static int calc_layout(struct ceph_osd_client *osdc, |
4729 | + struct ceph_vino vino, |
4730 | + struct ceph_file_layout *layout, |
4731 | + u64 off, u64 *plen, |
4732 | + struct ceph_osd_request *req, |
4733 | + struct ceph_osd_req_op *op) |
4734 | { |
4735 | u64 bno; |
4736 | + int r; |
4737 | |
4738 | - ceph_calc_raw_layout(osdc, layout, vino.snap, off, |
4739 | - plen, &bno, req, op); |
4740 | + r = ceph_calc_raw_layout(osdc, layout, vino.snap, off, |
4741 | + plen, &bno, req, op); |
4742 | + if (r < 0) |
4743 | + return r; |
4744 | |
4745 | snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); |
4746 | req->r_oid_len = strlen(req->r_oid); |
4747 | + |
4748 | + return r; |
4749 | } |
4750 | |
4751 | /* |
4752 | @@ -139,15 +147,14 @@ void ceph_osdc_release_request(struct kref *kref) |
4753 | |
4754 | if (req->r_request) |
4755 | ceph_msg_put(req->r_request); |
4756 | - if (req->r_reply) |
4757 | - ceph_msg_put(req->r_reply); |
4758 | if (req->r_con_filling_msg) { |
4759 | - dout("release_request revoking pages %p from con %p\n", |
4760 | + dout("%s revoking pages %p from con %p\n", __func__, |
4761 | req->r_pages, req->r_con_filling_msg); |
4762 | - ceph_con_revoke_message(req->r_con_filling_msg, |
4763 | - req->r_reply); |
4764 | - ceph_con_put(req->r_con_filling_msg); |
4765 | + ceph_msg_revoke_incoming(req->r_reply); |
4766 | + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); |
4767 | } |
4768 | + if (req->r_reply) |
4769 | + ceph_msg_put(req->r_reply); |
4770 | if (req->r_own_pages) |
4771 | ceph_release_page_vector(req->r_pages, |
4772 | req->r_num_pages); |
4773 | @@ -243,6 +250,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, |
4774 | } |
4775 | ceph_pagelist_init(req->r_trail); |
4776 | } |
4777 | + |
4778 | /* create request message; allow space for oid */ |
4779 | msg_size += MAX_OBJ_NAME_SIZE; |
4780 | if (snapc) |
4781 | @@ -256,7 +264,6 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, |
4782 | return NULL; |
4783 | } |
4784 | |
4785 | - msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP); |
4786 | memset(msg->front.iov_base, 0, msg->front.iov_len); |
4787 | |
4788 | req->r_request = msg; |
4789 | @@ -278,7 +285,7 @@ static void osd_req_encode_op(struct ceph_osd_request *req, |
4790 | { |
4791 | dst->op = cpu_to_le16(src->op); |
4792 | |
4793 | - switch (dst->op) { |
4794 | + switch (src->op) { |
4795 | case CEPH_OSD_OP_READ: |
4796 | case CEPH_OSD_OP_WRITE: |
4797 | dst->extent.offset = |
4798 | @@ -624,7 +631,7 @@ static void osd_reset(struct ceph_connection *con) |
4799 | /* |
4800 | * Track open sessions with osds. |
4801 | */ |
4802 | -static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) |
4803 | +static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) |
4804 | { |
4805 | struct ceph_osd *osd; |
4806 | |
4807 | @@ -634,15 +641,13 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) |
4808 | |
4809 | atomic_set(&osd->o_ref, 1); |
4810 | osd->o_osdc = osdc; |
4811 | + osd->o_osd = onum; |
4812 | INIT_LIST_HEAD(&osd->o_requests); |
4813 | INIT_LIST_HEAD(&osd->o_linger_requests); |
4814 | INIT_LIST_HEAD(&osd->o_osd_lru); |
4815 | osd->o_incarnation = 1; |
4816 | |
4817 | - ceph_con_init(osdc->client->msgr, &osd->o_con); |
4818 | - osd->o_con.private = osd; |
4819 | - osd->o_con.ops = &osd_con_ops; |
4820 | - osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; |
4821 | + ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr); |
4822 | |
4823 | INIT_LIST_HEAD(&osd->o_keepalive_item); |
4824 | return osd; |
4825 | @@ -664,11 +669,11 @@ static void put_osd(struct ceph_osd *osd) |
4826 | { |
4827 | dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), |
4828 | atomic_read(&osd->o_ref) - 1); |
4829 | - if (atomic_dec_and_test(&osd->o_ref)) { |
4830 | + if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) { |
4831 | struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; |
4832 | |
4833 | - if (osd->o_authorizer) |
4834 | - ac->ops->destroy_authorizer(ac, osd->o_authorizer); |
4835 | + if (ac->ops && ac->ops->destroy_authorizer) |
4836 | + ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer); |
4837 | kfree(osd); |
4838 | } |
4839 | } |
4840 | @@ -752,7 +757,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) |
4841 | ret = -EAGAIN; |
4842 | } else { |
4843 | ceph_con_close(&osd->o_con); |
4844 | - ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]); |
4845 | + ceph_con_open(&osd->o_con, CEPH_ENTITY_TYPE_OSD, osd->o_osd, |
4846 | + &osdc->osdmap->osd_addr[osd->o_osd]); |
4847 | osd->o_incarnation++; |
4848 | } |
4849 | return ret; |
4850 | @@ -841,13 +847,19 @@ static void register_request(struct ceph_osd_client *osdc, |
4851 | static void __unregister_request(struct ceph_osd_client *osdc, |
4852 | struct ceph_osd_request *req) |
4853 | { |
4854 | + if (RB_EMPTY_NODE(&req->r_node)) { |
4855 | + dout("__unregister_request %p tid %lld not registered\n", |
4856 | + req, req->r_tid); |
4857 | + return; |
4858 | + } |
4859 | + |
4860 | dout("__unregister_request %p tid %lld\n", req, req->r_tid); |
4861 | rb_erase(&req->r_node, &osdc->requests); |
4862 | osdc->num_requests--; |
4863 | |
4864 | if (req->r_osd) { |
4865 | /* make sure the original request isn't in flight. */ |
4866 | - ceph_con_revoke(&req->r_osd->o_con, req->r_request); |
4867 | + ceph_msg_revoke(req->r_request); |
4868 | |
4869 | list_del_init(&req->r_osd_item); |
4870 | if (list_empty(&req->r_osd->o_requests) && |
4871 | @@ -874,7 +886,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, |
4872 | static void __cancel_request(struct ceph_osd_request *req) |
4873 | { |
4874 | if (req->r_sent && req->r_osd) { |
4875 | - ceph_con_revoke(&req->r_osd->o_con, req->r_request); |
4876 | + ceph_msg_revoke(req->r_request); |
4877 | req->r_sent = 0; |
4878 | } |
4879 | } |
4880 | @@ -884,7 +896,9 @@ static void __register_linger_request(struct ceph_osd_client *osdc, |
4881 | { |
4882 | dout("__register_linger_request %p\n", req); |
4883 | list_add_tail(&req->r_linger_item, &osdc->req_linger); |
4884 | - list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests); |
4885 | + if (req->r_osd) |
4886 | + list_add_tail(&req->r_linger_osd, |
4887 | + &req->r_osd->o_linger_requests); |
4888 | } |
4889 | |
4890 | static void __unregister_linger_request(struct ceph_osd_client *osdc, |
4891 | @@ -992,18 +1006,18 @@ static int __map_request(struct ceph_osd_client *osdc, |
4892 | req->r_osd = __lookup_osd(osdc, o); |
4893 | if (!req->r_osd && o >= 0) { |
4894 | err = -ENOMEM; |
4895 | - req->r_osd = create_osd(osdc); |
4896 | + req->r_osd = create_osd(osdc, o); |
4897 | if (!req->r_osd) { |
4898 | list_move(&req->r_req_lru_item, &osdc->req_notarget); |
4899 | goto out; |
4900 | } |
4901 | |
4902 | dout("map_request osd %p is osd%d\n", req->r_osd, o); |
4903 | - req->r_osd->o_osd = o; |
4904 | - req->r_osd->o_con.peer_name.num = cpu_to_le64(o); |
4905 | __insert_osd(osdc, req->r_osd); |
4906 | |
4907 | - ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]); |
4908 | + ceph_con_open(&req->r_osd->o_con, |
4909 | + CEPH_ENTITY_TYPE_OSD, o, |
4910 | + &osdc->osdmap->osd_addr[o]); |
4911 | } |
4912 | |
4913 | if (req->r_osd) { |
4914 | @@ -1210,7 +1224,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, |
4915 | if (req->r_con_filling_msg == con && req->r_reply == msg) { |
4916 | dout(" dropping con_filling_msg ref %p\n", con); |
4917 | req->r_con_filling_msg = NULL; |
4918 | - ceph_con_put(con); |
4919 | + con->ops->put(con); |
4920 | } |
4921 | |
4922 | if (!req->r_got_reply) { |
4923 | @@ -1298,8 +1312,9 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) |
4924 | |
4925 | dout("kick_requests %s\n", force_resend ? " (force resend)" : ""); |
4926 | mutex_lock(&osdc->request_mutex); |
4927 | - for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { |
4928 | + for (p = rb_first(&osdc->requests); p; ) { |
4929 | req = rb_entry(p, struct ceph_osd_request, r_node); |
4930 | + p = rb_next(p); |
4931 | err = __map_request(osdc, req, force_resend); |
4932 | if (err < 0) |
4933 | continue; /* error */ |
4934 | @@ -1307,10 +1322,23 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) |
4935 | dout("%p tid %llu maps to no osd\n", req, req->r_tid); |
4936 | needmap++; /* request a newer map */ |
4937 | } else if (err > 0) { |
4938 | - dout("%p tid %llu requeued on osd%d\n", req, req->r_tid, |
4939 | - req->r_osd ? req->r_osd->o_osd : -1); |
4940 | - if (!req->r_linger) |
4941 | + if (!req->r_linger) { |
4942 | + dout("%p tid %llu requeued on osd%d\n", req, |
4943 | + req->r_tid, |
4944 | + req->r_osd ? req->r_osd->o_osd : -1); |
4945 | req->r_flags |= CEPH_OSD_FLAG_RETRY; |
4946 | + } |
4947 | + } |
4948 | + if (req->r_linger && list_empty(&req->r_linger_item)) { |
4949 | + /* |
4950 | + * register as a linger so that we will |
4951 | + * re-submit below and get a new tid |
4952 | + */ |
4953 | + dout("%p tid %llu restart on osd%d\n", |
4954 | + req, req->r_tid, |
4955 | + req->r_osd ? req->r_osd->o_osd : -1); |
4956 | + __register_linger_request(osdc, req); |
4957 | + __unregister_request(osdc, req); |
4958 | } |
4959 | } |
4960 | |
4961 | @@ -1385,7 +1413,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) |
4962 | epoch, maplen); |
4963 | newmap = osdmap_apply_incremental(&p, next, |
4964 | osdc->osdmap, |
4965 | - osdc->client->msgr); |
4966 | + &osdc->client->msgr); |
4967 | if (IS_ERR(newmap)) { |
4968 | err = PTR_ERR(newmap); |
4969 | goto bad; |
4970 | @@ -1833,11 +1861,12 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) |
4971 | if (!osdc->req_mempool) |
4972 | goto out; |
4973 | |
4974 | - err = ceph_msgpool_init(&osdc->msgpool_op, OSD_OP_FRONT_LEN, 10, true, |
4975 | + err = ceph_msgpool_init(&osdc->msgpool_op, CEPH_MSG_OSD_OP, |
4976 | + OSD_OP_FRONT_LEN, 10, true, |
4977 | "osd_op"); |
4978 | if (err < 0) |
4979 | goto out_mempool; |
4980 | - err = ceph_msgpool_init(&osdc->msgpool_op_reply, |
4981 | + err = ceph_msgpool_init(&osdc->msgpool_op_reply, CEPH_MSG_OSD_OPREPLY, |
4982 | OSD_OPREPLY_FRONT_LEN, 10, true, |
4983 | "osd_op_reply"); |
4984 | if (err < 0) |
4985 | @@ -2019,10 +2048,10 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, |
4986 | } |
4987 | |
4988 | if (req->r_con_filling_msg) { |
4989 | - dout("get_reply revoking msg %p from old con %p\n", |
4990 | + dout("%s revoking msg %p from old con %p\n", __func__, |
4991 | req->r_reply, req->r_con_filling_msg); |
4992 | - ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); |
4993 | - ceph_con_put(req->r_con_filling_msg); |
4994 | + ceph_msg_revoke_incoming(req->r_reply); |
4995 | + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); |
4996 | req->r_con_filling_msg = NULL; |
4997 | } |
4998 | |
4999 | @@ -2057,7 +2086,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, |
5000 | #endif |
5001 | } |
5002 | *skip = 0; |
5003 | - req->r_con_filling_msg = ceph_con_get(con); |
5004 | + req->r_con_filling_msg = con->ops->get(con); |
5005 | dout("get_reply tid %lld %p\n", tid, m); |
5006 | |
5007 | out: |
5008 | @@ -2074,6 +2103,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con, |
5009 | int type = le16_to_cpu(hdr->type); |
5010 | int front = le32_to_cpu(hdr->front_len); |
5011 | |
5012 | + *skip = 0; |
5013 | switch (type) { |
5014 | case CEPH_MSG_OSD_MAP: |
5015 | case CEPH_MSG_WATCH_NOTIFY: |
5016 | @@ -2108,37 +2138,32 @@ static void put_osd_con(struct ceph_connection *con) |
5017 | /* |
5018 | * authentication |
5019 | */ |
5020 | -static int get_authorizer(struct ceph_connection *con, |
5021 | - void **buf, int *len, int *proto, |
5022 | - void **reply_buf, int *reply_len, int force_new) |
5023 | +/* |
5024 | + * Note: returned pointer is the address of a structure that's |
5025 | + * managed separately. Caller must *not* attempt to free it. |
5026 | + */ |
5027 | +static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, |
5028 | + int *proto, int force_new) |
5029 | { |
5030 | struct ceph_osd *o = con->private; |
5031 | struct ceph_osd_client *osdc = o->o_osdc; |
5032 | struct ceph_auth_client *ac = osdc->client->monc.auth; |
5033 | - int ret = 0; |
5034 | + struct ceph_auth_handshake *auth = &o->o_auth; |
5035 | |
5036 | - if (force_new && o->o_authorizer) { |
5037 | - ac->ops->destroy_authorizer(ac, o->o_authorizer); |
5038 | - o->o_authorizer = NULL; |
5039 | - } |
5040 | - if (o->o_authorizer == NULL) { |
5041 | - ret = ac->ops->create_authorizer( |
5042 | - ac, CEPH_ENTITY_TYPE_OSD, |
5043 | - &o->o_authorizer, |
5044 | - &o->o_authorizer_buf, |
5045 | - &o->o_authorizer_buf_len, |
5046 | - &o->o_authorizer_reply_buf, |
5047 | - &o->o_authorizer_reply_buf_len); |
5048 | + if (force_new && auth->authorizer) { |
5049 | + if (ac->ops && ac->ops->destroy_authorizer) |
5050 | + ac->ops->destroy_authorizer(ac, auth->authorizer); |
5051 | + auth->authorizer = NULL; |
5052 | + } |
5053 | + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { |
5054 | + int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, |
5055 | + auth); |
5056 | if (ret) |
5057 | - return ret; |
5058 | + return ERR_PTR(ret); |
5059 | } |
5060 | - |
5061 | *proto = ac->protocol; |
5062 | - *buf = o->o_authorizer_buf; |
5063 | - *len = o->o_authorizer_buf_len; |
5064 | - *reply_buf = o->o_authorizer_reply_buf; |
5065 | - *reply_len = o->o_authorizer_reply_buf_len; |
5066 | - return 0; |
5067 | + |
5068 | + return auth; |
5069 | } |
5070 | |
5071 | |
5072 | @@ -2148,7 +2173,11 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) |
5073 | struct ceph_osd_client *osdc = o->o_osdc; |
5074 | struct ceph_auth_client *ac = osdc->client->monc.auth; |
5075 | |
5076 | - return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len); |
5077 | + /* |
5078 | + * XXX If ac->ops or ac->ops->verify_authorizer_reply is null, |
5079 | + * XXX which do we do: succeed or fail? |
5080 | + */ |
5081 | + return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len); |
5082 | } |
5083 | |
5084 | static int invalidate_authorizer(struct ceph_connection *con) |
5085 | @@ -2157,7 +2186,7 @@ static int invalidate_authorizer(struct ceph_connection *con) |
5086 | struct ceph_osd_client *osdc = o->o_osdc; |
5087 | struct ceph_auth_client *ac = osdc->client->monc.auth; |
5088 | |
5089 | - if (ac->ops->invalidate_authorizer) |
5090 | + if (ac->ops && ac->ops->invalidate_authorizer) |
5091 | ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD); |
5092 | |
5093 | return ceph_monc_validate_auth(&osdc->client->monc); |
5094 | diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c |
5095 | index 29ad46e..430076e 100644 |
5096 | --- a/net/ceph/osdmap.c |
5097 | +++ b/net/ceph/osdmap.c |
5098 | @@ -495,15 +495,16 @@ static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) |
5099 | ceph_decode_32_safe(p, end, pool, bad); |
5100 | ceph_decode_32_safe(p, end, len, bad); |
5101 | dout(" pool %d len %d\n", pool, len); |
5102 | + ceph_decode_need(p, end, len, bad); |
5103 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
5104 | if (pi) { |
5105 | + char *name = kstrndup(*p, len, GFP_NOFS); |
5106 | + |
5107 | + if (!name) |
5108 | + return -ENOMEM; |
5109 | kfree(pi->name); |
5110 | - pi->name = kmalloc(len + 1, GFP_NOFS); |
5111 | - if (pi->name) { |
5112 | - memcpy(pi->name, *p, len); |
5113 | - pi->name[len] = '\0'; |
5114 | - dout(" name is %s\n", pi->name); |
5115 | - } |
5116 | + pi->name = name; |
5117 | + dout(" name is %s\n", pi->name); |
5118 | } |
5119 | *p += len; |
5120 | } |
5121 | @@ -673,6 +674,9 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) |
5122 | ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); |
5123 | ceph_decode_copy(p, &pgid, sizeof(pgid)); |
5124 | n = ceph_decode_32(p); |
5125 | + err = -EINVAL; |
5126 | + if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) |
5127 | + goto bad; |
5128 | ceph_decode_need(p, end, n * sizeof(u32), bad); |
5129 | err = -ENOMEM; |
5130 | pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); |
5131 | @@ -890,8 +894,16 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, |
5132 | pglen = ceph_decode_32(p); |
5133 | |
5134 | if (pglen) { |
5135 | - /* insert */ |
5136 | ceph_decode_need(p, end, pglen*sizeof(u32), bad); |
5137 | + |
5138 | + /* removing existing (if any) */ |
5139 | + (void) __remove_pg_mapping(&map->pg_temp, pgid); |
5140 | + |
5141 | + /* insert */ |
5142 | + if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { |
5143 | + err = -EINVAL; |
5144 | + goto bad; |
5145 | + } |
5146 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); |
5147 | if (!pg) { |
5148 | err = -ENOMEM; |
5149 | @@ -940,7 +952,7 @@ bad: |
5150 | * for now, we write only a single su, until we can |
5151 | * pass a stride back to the caller. |
5152 | */ |
5153 | -void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
5154 | +int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
5155 | u64 off, u64 *plen, |
5156 | u64 *ono, |
5157 | u64 *oxoff, u64 *oxlen) |
5158 | @@ -954,11 +966,17 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
5159 | |
5160 | dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen, |
5161 | osize, su); |
5162 | + if (su == 0 || sc == 0) |
5163 | + goto invalid; |
5164 | su_per_object = osize / su; |
5165 | + if (su_per_object == 0) |
5166 | + goto invalid; |
5167 | dout("osize %u / su %u = su_per_object %u\n", osize, su, |
5168 | su_per_object); |
5169 | |
5170 | - BUG_ON((su & ~PAGE_MASK) != 0); |
5171 | + if ((su & ~PAGE_MASK) != 0) |
5172 | + goto invalid; |
5173 | + |
5174 | /* bl = *off / su; */ |
5175 | t = off; |
5176 | do_div(t, su); |
5177 | @@ -986,6 +1004,14 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
5178 | *plen = *oxlen; |
5179 | |
5180 | dout(" obj extent %llu~%llu\n", *oxoff, *oxlen); |
5181 | + return 0; |
5182 | + |
5183 | +invalid: |
5184 | + dout(" invalid layout\n"); |
5185 | + *ono = 0; |
5186 | + *oxoff = 0; |
5187 | + *oxlen = 0; |
5188 | + return -EINVAL; |
5189 | } |
5190 | EXPORT_SYMBOL(ceph_calc_file_object_mapping); |
5191 | |
5192 | diff --git a/net/core/dev.c b/net/core/dev.c |
5193 | index 24a21f3..eb858dc 100644 |
5194 | --- a/net/core/dev.c |
5195 | +++ b/net/core/dev.c |
5196 | @@ -2763,8 +2763,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, |
5197 | if (unlikely(tcpu != next_cpu) && |
5198 | (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || |
5199 | ((int)(per_cpu(softnet_data, tcpu).input_queue_head - |
5200 | - rflow->last_qtail)) >= 0)) |
5201 | + rflow->last_qtail)) >= 0)) { |
5202 | + tcpu = next_cpu; |
5203 | rflow = set_rps_cpu(dev, skb, rflow, next_cpu); |
5204 | + } |
5205 | |
5206 | if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { |
5207 | *rflowp = rflow; |
5208 | diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c |
5209 | index 626698f..76f6d0b 100644 |
5210 | --- a/net/core/dev_addr_lists.c |
5211 | +++ b/net/core/dev_addr_lists.c |
5212 | @@ -308,7 +308,8 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr, |
5213 | */ |
5214 | ha = list_first_entry(&dev->dev_addrs.list, |
5215 | struct netdev_hw_addr, list); |
5216 | - if (ha->addr == dev->dev_addr && ha->refcount == 1) |
5217 | + if (!memcmp(ha->addr, addr, dev->addr_len) && |
5218 | + ha->type == addr_type && ha->refcount == 1) |
5219 | return -ENOENT; |
5220 | |
5221 | err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, |
5222 | diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c |
5223 | index 2fd0fba..59ef40a 100644 |
5224 | --- a/net/ipv4/ip_sockglue.c |
5225 | +++ b/net/ipv4/ip_sockglue.c |
5226 | @@ -456,19 +456,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, |
5227 | struct inet_sock *inet = inet_sk(sk); |
5228 | int val = 0, err; |
5229 | |
5230 | - if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | |
5231 | - (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | |
5232 | - (1<<IP_RETOPTS) | (1<<IP_TOS) | |
5233 | - (1<<IP_TTL) | (1<<IP_HDRINCL) | |
5234 | - (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | |
5235 | - (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | |
5236 | - (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) | |
5237 | - (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) || |
5238 | - optname == IP_UNICAST_IF || |
5239 | - optname == IP_MULTICAST_TTL || |
5240 | - optname == IP_MULTICAST_ALL || |
5241 | - optname == IP_MULTICAST_LOOP || |
5242 | - optname == IP_RECVORIGDSTADDR) { |
5243 | + switch (optname) { |
5244 | + case IP_PKTINFO: |
5245 | + case IP_RECVTTL: |
5246 | + case IP_RECVOPTS: |
5247 | + case IP_RECVTOS: |
5248 | + case IP_RETOPTS: |
5249 | + case IP_TOS: |
5250 | + case IP_TTL: |
5251 | + case IP_HDRINCL: |
5252 | + case IP_MTU_DISCOVER: |
5253 | + case IP_RECVERR: |
5254 | + case IP_ROUTER_ALERT: |
5255 | + case IP_FREEBIND: |
5256 | + case IP_PASSSEC: |
5257 | + case IP_TRANSPARENT: |
5258 | + case IP_MINTTL: |
5259 | + case IP_NODEFRAG: |
5260 | + case IP_UNICAST_IF: |
5261 | + case IP_MULTICAST_TTL: |
5262 | + case IP_MULTICAST_ALL: |
5263 | + case IP_MULTICAST_LOOP: |
5264 | + case IP_RECVORIGDSTADDR: |
5265 | if (optlen >= sizeof(int)) { |
5266 | if (get_user(val, (int __user *) optval)) |
5267 | return -EFAULT; |
5268 | diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c |
5269 | index 3828a42..da4098f 100644 |
5270 | --- a/net/ipv4/netfilter/nf_nat_standalone.c |
5271 | +++ b/net/ipv4/netfilter/nf_nat_standalone.c |
5272 | @@ -194,7 +194,8 @@ nf_nat_out(unsigned int hooknum, |
5273 | |
5274 | if ((ct->tuplehash[dir].tuple.src.u3.ip != |
5275 | ct->tuplehash[!dir].tuple.dst.u3.ip) || |
5276 | - (ct->tuplehash[dir].tuple.src.u.all != |
5277 | + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && |
5278 | + ct->tuplehash[dir].tuple.src.u.all != |
5279 | ct->tuplehash[!dir].tuple.dst.u.all) |
5280 | ) |
5281 | return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; |
5282 | @@ -230,7 +231,8 @@ nf_nat_local_fn(unsigned int hooknum, |
5283 | ret = NF_DROP; |
5284 | } |
5285 | #ifdef CONFIG_XFRM |
5286 | - else if (ct->tuplehash[dir].tuple.dst.u.all != |
5287 | + else if (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && |
5288 | + ct->tuplehash[dir].tuple.dst.u.all != |
5289 | ct->tuplehash[!dir].tuple.src.u.all) |
5290 | if (ip_xfrm_me_harder(skb)) |
5291 | ret = NF_DROP; |
5292 | diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c |
5293 | index 63dd1f8..34c1109 100644 |
5294 | --- a/net/ipv6/ipv6_sockglue.c |
5295 | +++ b/net/ipv6/ipv6_sockglue.c |
5296 | @@ -828,6 +828,7 @@ pref_skip_coa: |
5297 | if (val < 0 || val > 255) |
5298 | goto e_inval; |
5299 | np->min_hopcount = val; |
5300 | + retv = 0; |
5301 | break; |
5302 | case IPV6_DONTFRAG: |
5303 | np->dontfrag = valbool; |
5304 | diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h |
5305 | index db8fae5..498e87b 100644 |
5306 | --- a/net/mac80211/ieee80211_i.h |
5307 | +++ b/net/mac80211/ieee80211_i.h |
5308 | @@ -1297,6 +1297,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, |
5309 | struct net_device *dev); |
5310 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
5311 | struct net_device *dev); |
5312 | +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, |
5313 | + struct sk_buff_head *skbs); |
5314 | |
5315 | /* HT */ |
5316 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); |
5317 | diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c |
5318 | index d93d39b..6d25d77 100644 |
5319 | --- a/net/mac80211/sta_info.c |
5320 | +++ b/net/mac80211/sta_info.c |
5321 | @@ -738,8 +738,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) |
5322 | |
5323 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
5324 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); |
5325 | - __skb_queue_purge(&sta->ps_tx_buf[ac]); |
5326 | - __skb_queue_purge(&sta->tx_filtered[ac]); |
5327 | + ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); |
5328 | + ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); |
5329 | } |
5330 | |
5331 | #ifdef CONFIG_MAC80211_MESH |
5332 | @@ -774,7 +774,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) |
5333 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); |
5334 | if (!tid_tx) |
5335 | continue; |
5336 | - __skb_queue_purge(&tid_tx->pending); |
5337 | + ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); |
5338 | kfree(tid_tx); |
5339 | } |
5340 | |
5341 | @@ -959,6 +959,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) |
5342 | struct ieee80211_local *local = sdata->local; |
5343 | struct sk_buff_head pending; |
5344 | int filtered = 0, buffered = 0, ac; |
5345 | + unsigned long flags; |
5346 | |
5347 | clear_sta_flag(sta, WLAN_STA_SP); |
5348 | |
5349 | @@ -974,12 +975,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) |
5350 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
5351 | int count = skb_queue_len(&pending), tmp; |
5352 | |
5353 | + spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); |
5354 | skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); |
5355 | + spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); |
5356 | tmp = skb_queue_len(&pending); |
5357 | filtered += tmp - count; |
5358 | count = tmp; |
5359 | |
5360 | + spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); |
5361 | skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); |
5362 | + spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); |
5363 | tmp = skb_queue_len(&pending); |
5364 | buffered += tmp - count; |
5365 | } |
5366 | diff --git a/net/mac80211/status.c b/net/mac80211/status.c |
5367 | index 5f8f89e..47b117f 100644 |
5368 | --- a/net/mac80211/status.c |
5369 | +++ b/net/mac80211/status.c |
5370 | @@ -660,3 +660,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) |
5371 | dev_kfree_skb_any(skb); |
5372 | } |
5373 | EXPORT_SYMBOL(ieee80211_free_txskb); |
5374 | + |
5375 | +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, |
5376 | + struct sk_buff_head *skbs) |
5377 | +{ |
5378 | + struct sk_buff *skb; |
5379 | + |
5380 | + while ((skb = __skb_dequeue(skbs))) |
5381 | + ieee80211_free_txskb(hw, skb); |
5382 | +} |
5383 | diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c |
5384 | index e76facc..eace766 100644 |
5385 | --- a/net/mac80211/tx.c |
5386 | +++ b/net/mac80211/tx.c |
5387 | @@ -1357,7 +1357,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) |
5388 | if (tx->skb) |
5389 | dev_kfree_skb(tx->skb); |
5390 | else |
5391 | - __skb_queue_purge(&tx->skbs); |
5392 | + ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); |
5393 | return -1; |
5394 | } else if (unlikely(res == TX_QUEUED)) { |
5395 | I802_DEBUG_INC(tx->local->tx_handlers_queued); |
5396 | @@ -2126,10 +2126,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
5397 | */ |
5398 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
5399 | { |
5400 | + struct sk_buff *skb; |
5401 | int i; |
5402 | |
5403 | - for (i = 0; i < local->hw.queues; i++) |
5404 | - skb_queue_purge(&local->pending[i]); |
5405 | + for (i = 0; i < local->hw.queues; i++) { |
5406 | + while ((skb = skb_dequeue(&local->pending[i])) != NULL) |
5407 | + ieee80211_free_txskb(&local->hw, skb); |
5408 | + } |
5409 | } |
5410 | |
5411 | /* |
5412 | diff --git a/net/mac80211/util.c b/net/mac80211/util.c |
5413 | index 266d092..73ef163 100644 |
5414 | --- a/net/mac80211/util.c |
5415 | +++ b/net/mac80211/util.c |
5416 | @@ -1341,6 +1341,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) |
5417 | list_for_each_entry(sdata, &local->interfaces, list) { |
5418 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
5419 | continue; |
5420 | + if (!sdata->u.mgd.associated) |
5421 | + continue; |
5422 | |
5423 | ieee80211_send_nullfunc(local, sdata, 0); |
5424 | } |
5425 | diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c |
5426 | index 0d07a1d..e022123 100644 |
5427 | --- a/net/netfilter/nf_conntrack_proto_tcp.c |
5428 | +++ b/net/netfilter/nf_conntrack_proto_tcp.c |
5429 | @@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { |
5430 | * sCL -> sSS |
5431 | */ |
5432 | /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ |
5433 | -/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, |
5434 | +/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR }, |
5435 | /* |
5436 | * sNO -> sIV Too late and no reason to do anything |
5437 | * sSS -> sIV Client can't send SYN and then SYN/ACK |
5438 | * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open |
5439 | - * sSR -> sIG |
5440 | - * sES -> sIG Error: SYNs in window outside the SYN_SENT state |
5441 | - * are errors. Receiver will reply with RST |
5442 | - * and close the connection. |
5443 | - * Or we are not in sync and hold a dead connection. |
5444 | - * sFW -> sIG |
5445 | - * sCW -> sIG |
5446 | - * sLA -> sIG |
5447 | - * sTW -> sIG |
5448 | - * sCL -> sIG |
5449 | + * sSR -> sSR Late retransmitted SYN/ACK in simultaneous open |
5450 | + * sES -> sIV Invalid SYN/ACK packets sent by the client |
5451 | + * sFW -> sIV |
5452 | + * sCW -> sIV |
5453 | + * sLA -> sIV |
5454 | + * sTW -> sIV |
5455 | + * sCL -> sIV |
5456 | */ |
5457 | /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ |
5458 | /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, |
5459 | @@ -627,15 +624,9 @@ static bool tcp_in_window(const struct nf_conn *ct, |
5460 | ack = sack = receiver->td_end; |
5461 | } |
5462 | |
5463 | - if (seq == end |
5464 | - && (!tcph->rst |
5465 | - || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT))) |
5466 | + if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT) |
5467 | /* |
5468 | - * Packets contains no data: we assume it is valid |
5469 | - * and check the ack value only. |
5470 | - * However RST segments are always validated by their |
5471 | - * SEQ number, except when seq == 0 (reset sent answering |
5472 | - * SYN. |
5473 | + * RST sent answering SYN. |
5474 | */ |
5475 | seq = end = sender->td_end; |
5476 | |
5477 | diff --git a/net/wireless/reg.c b/net/wireless/reg.c |
5478 | index b01449f..4dc8347 100644 |
5479 | --- a/net/wireless/reg.c |
5480 | +++ b/net/wireless/reg.c |
5481 | @@ -134,9 +134,8 @@ static const struct ieee80211_regdomain world_regdom = { |
5482 | .reg_rules = { |
5483 | /* IEEE 802.11b/g, channels 1..11 */ |
5484 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), |
5485 | - /* IEEE 802.11b/g, channels 12..13. No HT40 |
5486 | - * channel fits here. */ |
5487 | - REG_RULE(2467-10, 2472+10, 20, 6, 20, |
5488 | + /* IEEE 802.11b/g, channels 12..13. */ |
5489 | + REG_RULE(2467-10, 2472+10, 40, 6, 20, |
5490 | NL80211_RRF_PASSIVE_SCAN | |
5491 | NL80211_RRF_NO_IBSS), |
5492 | /* IEEE 802.11 channel 14 - Only JP enables |
5493 | diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c |
5494 | index 8636585..04aa5c8 100644 |
5495 | --- a/security/selinux/netnode.c |
5496 | +++ b/security/selinux/netnode.c |
5497 | @@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) |
5498 | if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { |
5499 | struct sel_netnode *tail; |
5500 | tail = list_entry( |
5501 | - rcu_dereference(sel_netnode_hash[idx].list.prev), |
5502 | + rcu_dereference_protected(sel_netnode_hash[idx].list.prev, |
5503 | + lockdep_is_held(&sel_netnode_lock)), |
5504 | struct sel_netnode, list); |
5505 | list_del_rcu(&tail->list); |
5506 | kfree_rcu(tail, rcu); |
5507 | diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c |
5508 | index 7143393..e23ad3f 100644 |
5509 | --- a/sound/pci/hda/patch_analog.c |
5510 | +++ b/sound/pci/hda/patch_analog.c |
5511 | @@ -544,6 +544,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) |
5512 | if (spec->multiout.dig_out_nid) { |
5513 | info++; |
5514 | codec->num_pcms++; |
5515 | + codec->spdif_status_reset = 1; |
5516 | info->name = "AD198x Digital"; |
5517 | info->pcm_type = HDA_PCM_TYPE_SPDIF; |
5518 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; |
5519 | diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c |
5520 | index 2bc6c51..057f95a2 100644 |
5521 | --- a/sound/pci/hda/patch_cirrus.c |
5522 | +++ b/sound/pci/hda/patch_cirrus.c |
5523 | @@ -95,8 +95,8 @@ enum { |
5524 | #define CS420X_VENDOR_NID 0x11 |
5525 | #define CS_DIG_OUT1_PIN_NID 0x10 |
5526 | #define CS_DIG_OUT2_PIN_NID 0x15 |
5527 | -#define CS_DMIC1_PIN_NID 0x12 |
5528 | -#define CS_DMIC2_PIN_NID 0x0e |
5529 | +#define CS_DMIC1_PIN_NID 0x0e |
5530 | +#define CS_DMIC2_PIN_NID 0x12 |
5531 | |
5532 | /* coef indices */ |
5533 | #define IDX_SPDIF_STAT 0x0000 |
5534 | @@ -1084,14 +1084,18 @@ static void init_input(struct hda_codec *codec) |
5535 | cs_automic(codec); |
5536 | |
5537 | coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ |
5538 | + cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); |
5539 | + |
5540 | + coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); |
5541 | if (is_active_pin(codec, CS_DMIC2_PIN_NID)) |
5542 | - coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ |
5543 | + coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ |
5544 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) |
5545 | - coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off |
5546 | + coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off |
5547 | * No effect if SPDIF_OUT2 is |
5548 | * selected in IDX_SPDIF_CTL. |
5549 | */ |
5550 | - cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); |
5551 | + |
5552 | + cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); |
5553 | } else { |
5554 | if (spec->mic_detect) |
5555 | cs_automic(codec); |
5556 | @@ -1112,7 +1116,7 @@ static const struct hda_verb cs_coef_init_verbs[] = { |
5557 | | 0x0400 /* Disable Coefficient Auto increment */ |
5558 | )}, |
5559 | /* Beep */ |
5560 | - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, |
5561 | + {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, |
5562 | {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ |
5563 | |
5564 | {} /* terminator */ |
5565 | diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c |
5566 | index 6ecf1d4..257fe87 100644 |
5567 | --- a/sound/pci/hda/patch_realtek.c |
5568 | +++ b/sound/pci/hda/patch_realtek.c |
5569 | @@ -5458,6 +5458,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
5570 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), |
5571 | SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), |
5572 | SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), |
5573 | + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), |
5574 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), |
5575 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), |
5576 | SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), |
5577 | @@ -7047,6 +7048,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { |
5578 | .patch = patch_alc662 }, |
5579 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
5580 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, |
5581 | + { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, |
5582 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, |
5583 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, |
5584 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
5585 | @@ -7064,6 +7066,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { |
5586 | { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, |
5587 | { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, |
5588 | { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, |
5589 | + { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 }, |
5590 | {} /* terminator */ |
5591 | }; |
5592 | |
5593 | diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c |
5594 | index 3998d09b..9dafacd 100644 |
5595 | --- a/sound/pci/hda/patch_via.c |
5596 | +++ b/sound/pci/hda/patch_via.c |
5597 | @@ -1868,11 +1868,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) |
5598 | { |
5599 | struct via_spec *spec = codec->spec; |
5600 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
5601 | - int i, dac_num; |
5602 | + int i; |
5603 | hda_nid_t nid; |
5604 | |
5605 | + spec->multiout.num_dacs = 0; |
5606 | spec->multiout.dac_nids = spec->private_dac_nids; |
5607 | - dac_num = 0; |
5608 | for (i = 0; i < cfg->line_outs; i++) { |
5609 | hda_nid_t dac = 0; |
5610 | nid = cfg->line_out_pins[i]; |
5611 | @@ -1883,16 +1883,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) |
5612 | if (!i && parse_output_path(codec, nid, dac, 1, |
5613 | &spec->out_mix_path)) |
5614 | dac = spec->out_mix_path.path[0]; |
5615 | - if (dac) { |
5616 | - spec->private_dac_nids[i] = dac; |
5617 | - dac_num++; |
5618 | - } |
5619 | + if (dac) |
5620 | + spec->private_dac_nids[spec->multiout.num_dacs++] = dac; |
5621 | } |
5622 | if (!spec->out_path[0].depth && spec->out_mix_path.depth) { |
5623 | spec->out_path[0] = spec->out_mix_path; |
5624 | spec->out_mix_path.depth = 0; |
5625 | } |
5626 | - spec->multiout.num_dacs = dac_num; |
5627 | return 0; |
5628 | } |
5629 | |
5630 | @@ -3668,6 +3665,18 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) |
5631 | update_power_state(codec, 0x21, AC_PWRST_D3); |
5632 | } |
5633 | |
5634 | +/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e |
5635 | + * Replace this with mixer NID 0x1c |
5636 | + */ |
5637 | +static void fix_vt1802_connections(struct hda_codec *codec) |
5638 | +{ |
5639 | + static hda_nid_t conn_24[] = { 0x14, 0x1c }; |
5640 | + static hda_nid_t conn_33[] = { 0x1c }; |
5641 | + |
5642 | + snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); |
5643 | + snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); |
5644 | +} |
5645 | + |
5646 | /* patch for vt2002P */ |
5647 | static int patch_vt2002P(struct hda_codec *codec) |
5648 | { |
5649 | @@ -3682,6 +3691,8 @@ static int patch_vt2002P(struct hda_codec *codec) |
5650 | spec->aa_mix_nid = 0x21; |
5651 | override_mic_boost(codec, 0x2b, 0, 3, 40); |
5652 | override_mic_boost(codec, 0x29, 0, 3, 40); |
5653 | + if (spec->codec_type == VT1802) |
5654 | + fix_vt1802_connections(codec); |
5655 | add_secret_dac_path(codec); |
5656 | |
5657 | /* automatic parse from the BIOS config */ |
5658 | diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c |
5659 | index 72d5fdc..6c37c7c 100644 |
5660 | --- a/sound/soc/codecs/wm8978.c |
5661 | +++ b/sound/soc/codecs/wm8978.c |
5662 | @@ -783,7 +783,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, |
5663 | wm8978->mclk_idx = -1; |
5664 | f_sel = wm8978->f_mclk; |
5665 | } else { |
5666 | - if (!wm8978->f_pllout) { |
5667 | + if (!wm8978->f_opclk) { |
5668 | /* We only enter here, if OPCLK is not used */ |
5669 | int ret = wm8978_configure_pll(codec); |
5670 | if (ret < 0) |
5671 | diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c |
5672 | index c41efe0..9ae82a4 100644 |
5673 | --- a/sound/soc/soc-dapm.c |
5674 | +++ b/sound/soc/soc-dapm.c |
5675 | @@ -3253,7 +3253,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) |
5676 | { |
5677 | struct snd_soc_codec *codec; |
5678 | |
5679 | - list_for_each_entry(codec, &card->codec_dev_list, list) { |
5680 | + list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
5681 | soc_dapm_shutdown_codec(&codec->dapm); |
5682 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) |
5683 | snd_soc_dapm_set_bias_level(&codec->dapm, |