]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/libfc-ensure-correct-device_pu.diff
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / libfc-ensure-correct-device_pu.diff
CommitLineData
4d1e5b62
AF
1From: Robert Love <robert.w.love@intel.com>
2Subject: libfc: Ensure correct device_put/get usage (round 2)
3References:
4
5Reference counting was barely used and where used
6it was incorrect. This patch creates a few simple
7policies.
8
9When the rport->dev [e.g. struct device] is initialized
10it starts with a refcnt of 1. Whenever we're using the
11rport we will increment the count. When we logoff we
12should decrement the count to 0 and the 'release'
13function will be called. The FC transport provides the
14release function for real rports and libfc provides it
15for rogue rports. When we switch from a rogue to real
16rport we'll decrement the refcnt on the rogue rport
17and increment it for the real rport, after we've created
18it.
19
20Any externally initiated action on an rport (login,
21logoff) will not require the caller to increment and
22decrement the refcnt.
23
24For rport_login(), the rport will have just been created
25and therefore no other thread would be able to access
26this object.
27
28For rport_logoff(), the rport will have been removed
29from the list of rports and therefore no other thread
30would be able to lookup() this rport.
31
32This patch removes the get_device() from the rport_lookup
33function. These are the places where it is called and why
34we don't need a reference.
35
36fc_disc_recv_rscn_req() - called for single port RSCNs
37 the disc mutex is held and
38 ensures that no other thread
39 will find this rport.
40
41fc_disc_new_target() - Same. The rport cannot be looked up
42 so no other thread can free the rport.
43 This code looks buggy though, we
44 shouldn't be calling rport_login() on
45 a 'real' rport, which we could do.
46
47fc_disc_single() - Same. disc mutex protects the list.
48
49fc_lport_recv_req() - Similar, but this time the lport lock
50 ensures that no incoming requests are
51 processed until the current request
52 for an rport has returned.
53
54When the rport layer needs to send a request it will
55increment the count so that the EM can be confident that
56the rport is present when making the callback. If
57fc_remote_port_delete() is called before the response
58callback, which is often the case for LOGO commands, the
59refcnt will still have a value of 1 becuase we grabbed the
60lock before the ctels_send() is called. The exchange would
61have been removed and so the callback will be called with
62an error code. After processing the error code we'll
63decrement the refcnt for the last time and the rport will
64be free'd.
65
66Since point-to-point mode is not working this patch
67does not consider point-to-point.
68
69Signed-off-by: Robert Love <robert.w.love@intel.com>
70Acked-by: Bernhard Walle <bwalle@suse.de>
71---
72
73 drivers/scsi/libfc/fc_disc.c | 5 +----
74 drivers/scsi/libfc/fc_lport.c | 5 ++---
75 drivers/scsi/libfc/fc_rport.c | 21 ++++++++++++++-------
76 3 files changed, 17 insertions(+), 14 deletions(-)
77
78
79--- a/drivers/scsi/libfc/fc_disc.c
80+++ b/drivers/scsi/libfc/fc_disc.c
81@@ -81,7 +81,6 @@ struct fc_rport *fc_disc_lookup_rport(co
82 if (rport->port_id == port_id) {
83 disc_found = 1;
84 found = rport;
85- get_device(&found->dev);
86 break;
87 }
88 }
89@@ -767,10 +766,8 @@ static void fc_disc_single(struct fc_dis
90 goto out;
91
92 rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
93- if (rport) {
94+ if (rport)
95 fc_disc_del_target(disc, rport);
96- put_device(&rport->dev); /* hold from lookup */
97- }
98
99 new_rport = fc_rport_rogue_create(dp);
100 if (new_rport) {
101--- a/drivers/scsi/libfc/fc_lport.c
102+++ b/drivers/scsi/libfc/fc_lport.c
103@@ -908,10 +908,9 @@ static void fc_lport_recv_req(struct fc_
104 d_id = ntoh24(fh->fh_d_id);
105
106 rport = lport->tt.rport_lookup(lport, s_id);
107- if (rport) {
108+ if (rport)
109 lport->tt.rport_recv_req(sp, fp, rport);
110- put_device(&rport->dev); /* hold from lookup */
111- } else {
112+ else {
113 rjt_data.fp = NULL;
114 rjt_data.reason = ELS_RJT_UNAB;
115 rjt_data.explan = ELS_EXPL_NONE;
116--- a/drivers/scsi/libfc/fc_rport.c
117+++ b/drivers/scsi/libfc/fc_rport.c
118@@ -111,16 +111,11 @@ struct fc_rport *fc_rport_rogue_create(s
119 rport->roles = dp->ids.roles;
120 rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
121 /*
122- * init the device, so other code can manipulate the rport as if
123- * it came from the fc class. We also do an extra get because
124- * libfc will free this rport instead of relying on the normal
125- * refcounting.
126- *
127 * Note: all this libfc rogue rport code will be removed for
128 * upstream so it fine that this is really ugly and hacky right now.
129 */
130 device_initialize(&rport->dev);
131- get_device(&rport->dev);
132+ rport->dev.release = fc_rport_rogue_destroy; // XXX: bwalle
133
134 mutex_init(&rdata->rp_mutex);
135 rdata->local_port = dp->lp;
136@@ -402,9 +397,9 @@ static void fc_rport_timeout(struct work
137 case RPORT_ST_NONE:
138 break;
139 }
140- put_device(&rport->dev);
141
142 mutex_unlock(&rdata->rp_mutex);
143+ put_device(&rport->dev);
144 }
145
146 /**
147@@ -531,6 +526,7 @@ out:
148 fc_frame_free(fp);
149 err:
150 mutex_unlock(&rdata->rp_mutex);
151+ put_device(&rport->dev);
152 }
153
154 /**
155@@ -562,6 +558,8 @@ static void fc_rport_enter_plogi(struct
156 if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI,
157 fc_rport_plogi_resp, rport, lport->e_d_tov))
158 fc_rport_error(rport, fp);
159+ else
160+ get_device(&rport->dev);
161 }
162
163 /**
164@@ -631,6 +629,7 @@ out:
165 fc_frame_free(fp);
166 err:
167 mutex_unlock(&rdata->rp_mutex);
168+ put_device(&rport->dev);
169 }
170
171 /**
172@@ -679,6 +678,7 @@ out:
173 fc_frame_free(fp);
174 err:
175 mutex_unlock(&rdata->rp_mutex);
176+ put_device(&rport->dev);
177 }
178
179 /**
180@@ -712,6 +712,8 @@ static void fc_rport_enter_prli(struct f
181 if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI,
182 fc_rport_prli_resp, rport, lport->e_d_tov))
183 fc_rport_error(rport, fp);
184+ else
185+ get_device(&rport->dev);
186 }
187
188 /**
189@@ -777,6 +779,7 @@ out:
190 fc_frame_free(fp);
191 err:
192 mutex_unlock(&rdata->rp_mutex);
193+ put_device(&rport->dev);
194 }
195
196 /**
197@@ -806,6 +809,8 @@ static void fc_rport_enter_rtv(struct fc
198 if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV,
199 fc_rport_rtv_resp, rport, lport->e_d_tov))
200 fc_rport_error(rport, fp);
201+ else
202+ get_device(&rport->dev);
203 }
204
205 /**
206@@ -835,6 +840,8 @@ static void fc_rport_enter_logo(struct f
207 if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO,
208 fc_rport_logo_resp, rport, lport->e_d_tov))
209 fc_rport_error(rport, fp);
210+ else
211+ get_device(&rport->dev);
212 }
213
214