ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-NBD/NBD.xs
(Generate patch)

Comparing Linux-NBD/NBD.xs (file contents):
Revision 1.5 by root, Mon Sep 20 11:14:25 2010 UTC vs.
Revision 1.6 by root, Tue Sep 21 11:31:05 2010 UTC

20#define ntohll(netlong) __bswap_64(netlong) 20#define ntohll(netlong) __bswap_64(netlong)
21#else 21#else
22error, you should not exist 22error, you should not exist
23#endif 23#endif
24 24
25struct rstate {
26 struct nbd_request req;
27 u32 req_read; /* how many octets of req are valid */
28 u32 data_read; /* how many octets of the data sv are valid */
29};
30
25MODULE = Linux::NBD PACKAGE = Linux::NBD::Client 31MODULE = Linux::NBD PACKAGE = Linux::NBD::Client
32
33PROTOTYPES: DISABLE
26 34
27void 35void
28_set_sock (int dev, int fd) 36_set_sock (int dev, int fd)
29 CODE: 37 CODE:
30 ioctl (dev, NBD_SET_SOCK, (unsigned long)fd); 38 ioctl (dev, NBD_SET_SOCK, (unsigned long)fd);
86 94
87void 95void
88_one_request (SV *obj, int fd) 96_one_request (SV *obj, int fd)
89 CODE: 97 CODE:
90{ 98{
91 struct nbd_request req; 99 struct rstate *s;
100 u64 from;
101 u32 len;
102 char *method;
103 MAGIC *mg = mg_find (SvRV (obj), PERL_MAGIC_ext);
92 104
93 if (read (fd, &req, sizeof (req)) == sizeof (req)) 105 if (!mg)
94 { 106 {
95 if (req.magic == htonl (NBD_REQUEST_MAGIC)) 107 mg = sv_magicext (SvRV (obj), 0, PERL_MAGIC_ext, 0, 0, 0);
96 { 108 mg->mg_len = sizeof (struct rstate);
97 req.type = htonl (req.type); 109 New (0, mg->mg_ptr, mg->mg_len, char);
98 110
99 if (req.type < 2) 111 ((struct rstate *)mg->mg_ptr)->req_read = 0; /* initialise the state machine */
100 {
101 u64 from = ntohll (req.from);
102
103 PUSHMARK (SP);
104 EXTEND (SP, 3);
105 PUSHs (obj);
106 PUSHs (sv_2mortal (newSVpvn (req.handle, sizeof (req.handle))));
107 PUSHs (sv_2mortal (sizeof (UV) < 8 && from > (0xffffffffUL)
108 ? newSVnv (from)
109 : newSVuv (from)));
110 PUSHs (sv_2mortal (newSVuv (ntohl (req.len))));
111 PUTBACK;
112 call_method (req.type ? "req_write" : "req_read", G_DISCARD);
113 SPAGAIN;
114
115 XSRETURN_NO;
116 }
117 }
118 } 112 }
113
114 s = (struct rstate *)mg->mg_ptr;
115
116 if (s->req_read < sizeof (struct nbd_request))
117 {
118 int res = read (fd, s->req_read + (char *)&s->req, sizeof (struct nbd_request) - s->req_read);
119
120 if (res > 0)
121 s->req_read += res;
122 else if (res == 0)
123 XSRETURN_UNDEF; /* should req->eof */
124 else if (errno != EAGAIN && errno != EWOULDBLOCK)
125 XSRETURN_UNDEF; /* should req->error */
126
127 s->data_read = 0;
128 }
129
130 if (s->req_read < sizeof (struct nbd_request))
131 XSRETURN_NO;
132
133 /* now we have a full request, so check for data */
134 if (s->req.magic != htonl (NBD_REQUEST_MAGIC))
135 croak ("Linux::NBD::Server received illegal request magic %08lx - protocol error.\n", ntohl (s->req.magic));
136
137 from = ntohll (s->req.from);
138 len = ntohl (s->req.len);
139
140 switch (ntohl (s->req.type))
141 {
142 case NBD_CMD_WRITE:
143 if (!mg->mg_obj)
144 {
145 mg->mg_flags |= MGf_REFCOUNTED;
146 mg->mg_obj = NEWSV (0, len);
147 SvPOK_only (mg->mg_obj);
148 SvCUR_set (mg->mg_obj, len);
149 }
150
151 if (s->data_read < len)
152 {
153 int res = read (fd, s->data_read + SvPVX (mg->mg_obj), len - s->data_read);
154
155 if (res > 0)
156 s->data_read += res;
157 else if (res == 0)
158 XSRETURN_UNDEF; /* should req->eof */
159 else if (errno != EAGAIN && errno != EWOULDBLOCK)
160 XSRETURN_UNDEF; /* should req->error */
161 }
162
163 if (s->data_read < len)
164 XSRETURN_NO;
165
166 /* fallthrough */
167 case NBD_CMD_READ:
168 s->req_read = 0;
169
170 PUSHMARK (SP);
171 EXTEND (SP, 4);
172 PUSHs (obj);
173 PUSHs (sv_2mortal (newSVpvn (s->req.handle, sizeof (s->req.handle))));
174 PUSHs (sv_2mortal (sizeof (UV) < 8 && from > 0xffffffffUL
175 ? newSVnv (from)
176 : newSVuv (from)));
177
178 if (mg->mg_obj)
179 {
180 PUSHs (sv_2mortal (mg->mg_obj));
181 mg->mg_obj = 0;
182 method = "req_write";
183 }
184 else
185 {
186 PUSHs (sv_2mortal (newSVuv (len)));
187 method = "req_read";
188 }
189
190 break;
191
192 case NBD_CMD_DISC:
193 s->req_read = 0;
194
195 method = "req_disc";
196
197 PUSHMARK (SP);
198 XPUSHs (obj);
199
200 break;
201
202 default:
203 croak ("Linux::NBD::Server received unsupported request type %d.\n", ntohl (s->req.type));
204 }
205
206 PUTBACK;
207 call_method (method, G_DISCARD);
208 SPAGAIN;
119 209
120 XSRETURN_YES; 210 XSRETURN_YES;
121} 211}
122 212
123SV * 213SV *
124_format_reply (SV *handle, unsigned int error = 0, SV *data = 0) 214format_reply (SV *unused, SV *handle, unsigned int error = 0, SV *data = 0)
125 CODE: 215 CODE:
126{ 216{
127 struct nbd_reply rep; 217 struct nbd_reply rep;
128 STRLEN len; 218 STRLEN len;
129 char *h = SvPV (handle, len); 219 char *h = SvPV (handle, len);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines