ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-NBD/NBD.xs
Revision: 1.9
Committed: Tue May 30 03:58:30 2017 UTC (6 years, 11 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +7 -5 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     #include <inttypes.h>
6     #include <unistd.h>
7     #include <endian.h>
8    
9     #include <sys/ioctl.h>
10     #include <netinet/in.h>
11     #include <byteswap.h>
12    
13     typedef uint32_t u32;
14     typedef uint64_t u64;
15 root 1.8 #include "nbd.h"
16 root 1.1
17     #if __BYTE_ORDER == __BIG_ENDIAN
18     #define ntohll(netlong) (netlong)
19     #elif __BYTE_ORDER == __LITTLE_ENDIAN
20     #define ntohll(netlong) __bswap_64(netlong)
21     #else
22     error, you should not exist
23     #endif
24    
25 root 1.6 struct 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    
31 root 1.1 MODULE = Linux::NBD PACKAGE = Linux::NBD::Client
32    
33 root 1.6 PROTOTYPES: DISABLE
34    
35 root 1.1 void
36     _set_sock (int dev, int fd)
37     CODE:
38     ioctl (dev, NBD_SET_SOCK, (unsigned long)fd);
39    
40     void
41 root 1.2 _doit (int dev, int server = 0)
42 root 1.1 CODE:
43 root 1.2 if (server)
44     for (server = 0; server < 4095; server++)
45     if (server != dev)
46     close (server);
47    
48 root 1.1 ioctl (dev, NBD_DO_IT);
49 root 1.2
50     if (server)
51 root 1.1 _exit (0);
52    
53     void
54     _disconnect (int dev)
55     CODE:
56     ioctl (dev, NBD_DISCONNECT);
57    
58     void
59     _clear_sock (int dev)
60 root 1.8 ALIAS:
61     _clear_sock = NBD_CLEAR_SOCK
62     _clear_que = NBD_CLEAR_QUE
63     CODE:
64     ioctl (dev, ix);
65    
66     void
67     _set_blksize (int dev, unsigned long arg)
68     ALIAS:
69     _set_blksize = NBD_SET_BLKSIZE
70     _set_size = NBD_SET_SIZE
71     _set_size_blocks = NBD_SET_SIZE_BLOCKS
72     _set_timeout = NBD_SET_TIMEOUT
73     _set_flags = NBD_SET_FLAGS
74 root 1.1 CODE:
75 root 1.8 ioctl (dev, ix, arg);
76 root 1.5
77     void
78     _print_debug (int dev)
79     CODE:
80     ioctl (dev, NBD_PRINT_DEBUG, 0);
81    
82 root 1.1 MODULE = Linux::NBD PACKAGE = Linux::NBD::Server
83    
84     void
85     _one_request (SV *obj, int fd)
86     CODE:
87 root 1.3 {
88 root 1.6 struct rstate *s;
89     u64 from;
90     u32 len;
91     char *method;
92 root 1.9 int cmd;
93 root 1.6 MAGIC *mg = mg_find (SvRV (obj), PERL_MAGIC_ext);
94    
95     if (!mg)
96     {
97     mg = sv_magicext (SvRV (obj), 0, PERL_MAGIC_ext, 0, 0, 0);
98     mg->mg_len = sizeof (struct rstate);
99     New (0, mg->mg_ptr, mg->mg_len, char);
100    
101     ((struct rstate *)mg->mg_ptr)->req_read = 0; /* initialise the state machine */
102     }
103    
104     s = (struct rstate *)mg->mg_ptr;
105 root 1.1
106 root 1.6 if (s->req_read < sizeof (struct nbd_request))
107 root 1.1 {
108 root 1.6 int res = read (fd, s->req_read + (char *)&s->req, sizeof (struct nbd_request) - s->req_read);
109    
110     if (res > 0)
111     s->req_read += res;
112     else if (res == 0)
113     XSRETURN_UNDEF; /* should req->eof */
114     else if (errno != EAGAIN && errno != EWOULDBLOCK)
115     XSRETURN_UNDEF; /* should req->error */
116    
117     s->data_read = 0;
118 root 1.7
119     if (s->req_read < sizeof (struct nbd_request))
120     XSRETURN_NO;
121 root 1.1 }
122    
123 root 1.6 /* now we have a full request, so check for data */
124     if (s->req.magic != htonl (NBD_REQUEST_MAGIC))
125     croak ("Linux::NBD::Server received illegal request magic %08lx - protocol error.\n", ntohl (s->req.magic));
126    
127     from = ntohll (s->req.from);
128     len = ntohl (s->req.len);
129 root 1.9 cmd = ntohl (s->req.type) & NBD_CMD_MASK_COMMAND;
130 root 1.6
131 root 1.9 switch (cmd)
132 root 1.6 {
133     case NBD_CMD_WRITE:
134     if (!mg->mg_obj)
135     {
136     mg->mg_flags |= MGf_REFCOUNTED;
137     mg->mg_obj = NEWSV (0, len);
138     SvPOK_only (mg->mg_obj);
139     SvCUR_set (mg->mg_obj, len);
140     }
141    
142     if (s->data_read < len)
143     {
144     int res = read (fd, s->data_read + SvPVX (mg->mg_obj), len - s->data_read);
145    
146     if (res > 0)
147     s->data_read += res;
148     else if (res == 0)
149     XSRETURN_UNDEF; /* should req->eof */
150     else if (errno != EAGAIN && errno != EWOULDBLOCK)
151     XSRETURN_UNDEF; /* should req->error */
152 root 1.7
153     if (s->data_read < len)
154     XSRETURN_NO;
155 root 1.6 }
156    
157     /* fallthrough */
158     case NBD_CMD_READ:
159 root 1.8 case NBD_CMD_FLUSH:
160     case NBD_CMD_TRIM:
161     case NBD_CMD_WRITE_ZEROES:
162 root 1.6 s->req_read = 0;
163    
164     PUSHMARK (SP);
165     EXTEND (SP, 4);
166     PUSHs (obj);
167     PUSHs (sv_2mortal (newSVpvn (s->req.handle, sizeof (s->req.handle))));
168     PUSHs (sv_2mortal (sizeof (UV) < 8 && from > 0xffffffffUL
169     ? newSVnv (from)
170     : newSVuv (from)));
171    
172     if (mg->mg_obj)
173     {
174     PUSHs (sv_2mortal (mg->mg_obj));
175     mg->mg_obj = 0;
176     method = "req_write";
177     }
178     else
179     {
180     PUSHs (sv_2mortal (newSVuv (len)));
181 root 1.9 method = cmd == NBD_CMD_READ ? "req_read"
182     : cmd == NBD_CMD_FLUSH ? "req_flush"
183     : cmd == NBD_CMD_TRIM ? "req_trim"
184     : cmd == NBD_CMD_WRITE_ZEROES ? "req_write_zeroes"
185 root 1.8 : (abort (), "");
186 root 1.6 }
187    
188     break;
189    
190     case NBD_CMD_DISC:
191     s->req_read = 0;
192    
193     method = "req_disc";
194    
195     PUSHMARK (SP);
196     XPUSHs (obj);
197    
198     break;
199    
200     default:
201     croak ("Linux::NBD::Server received unsupported request type %d.\n", ntohl (s->req.type));
202     }
203    
204     PUTBACK;
205     call_method (method, G_DISCARD);
206     SPAGAIN;
207    
208 root 1.1 XSRETURN_YES;
209 root 1.3 }
210 root 1.1
211     SV *
212 root 1.6 format_reply (SV *unused, SV *handle, unsigned int error = 0, SV *data = 0)
213 root 1.1 CODE:
214 root 1.3 {
215 root 1.1 struct nbd_reply rep;
216     STRLEN len;
217     char *h = SvPV (handle, len);
218    
219     if (len != sizeof (rep.handle))
220     croak ("format_reply: illegal handle (length %d, should be %d)", len, sizeof (rep.handle));
221    
222     rep.magic = htonl (NBD_REPLY_MAGIC);
223     rep.error = htonl (error);
224     memcpy (rep.handle, h, sizeof (rep.handle));
225    
226     RETVAL = newSVpvn ((char *)&rep, sizeof (rep));
227    
228     if (data && !error)
229     sv_catsv (RETVAL, data);
230 root 1.8 }
231 root 1.1 OUTPUT:
232     RETVAL
233