ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Linux-NBD/lib/Linux/NBD/Client.pm
Revision: 1.13
Committed: Tue Sep 21 11:51:55 2010 UTC (16 years ago) by root
Branch: MAIN
CVS Tags: rel-1_0
Changes since 1.12: +5 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.9 Linux::NBD::Client - client (device) side of a network block device
4 root 1.1
5     =head1 SYNOPSIS
6    
7     use Linux::NBD::Client;
8    
9     =head1 DESCRIPTION
10    
11 root 1.4 WARNING: I talked to the author of the nbd driver because nbd is so
12     extremely racy (right now, stopping it often causes oopses, a server
13     crashing also often oopses etc..).
14    
15     It turned out that he doesn't care at all and nbd is basically
16     unmaintained, so YMMV when using this module, especially when writing
17     servers.
18    
19     He really should have said that on his nbd pages ;[.
20    
21     OTOH, it works relatively reliable when you don't stop the servers, so
22     watch out and keep your fingers crossed.
23 root 1.1
24     =head1 METHODS
25    
26     =over 4
27    
28     =cut
29    
30     package Linux::NBD::Client;
31    
32 root 1.7 $VERSION = 0.21;
33 root 1.1
34     use Linux::NBD ();
35    
36     use Carp qw(croak);
37     use Errno ();
38    
39 root 1.12 =item $client = new Linux::NBD::Client [socket => $fh][, device => "/dev/nbdX"], ...
40 root 1.1
41     Create a new client.
42    
43     Unless C<device> is given, an unused device node is looked up using the
44     C<device> method (this might result in an exception!).
45    
46 root 1.10 =item $client->socket ([$tcp_socket])
47 root 1.1
48     Returns the current socket after setting a new one (if an argument is
49 root 1.10 supplied). The socket I<MUST> be a tcp socket. Believe me, bad things will
50     happen if not.
51 root 1.1
52     The special argument C<undef> will try to clear the socket, if any was
53     set.
54    
55 root 1.10 =item $client->device ([$new_device])
56 root 1.1
57 root 1.12 Returns the current device node (e.g. C</dev/nbd2>) after setting a new one if
58 root 1.1 an argument is supplied.
59    
60     If the argument is C<undef> it will search for an unallocated nbd-device
61     and use it.
62    
63     =cut
64    
65     sub new {
66     my $class = shift;
67     my $self = bless { @_ }, $class;
68    
69     $self->device (exists $self->{device} ? $self->{device} : undef);
70 root 1.12 exists $self->{socket} and $self->socket ($self->{socket});
71 root 1.1
72     $self;
73     }
74    
75     sub socket {
76     my $self = shift;
77    
78     if (@_) {
79     $self->{socket} = $_[0];
80    
81     if (defined $self->{socket}) {
82     my $fileno = $_[0] =~ /[^0-9]/ ? fileno $_[0] : $_[0];
83     _set_sock fileno $self->{device_fd}, $fileno;
84     } else {
85     _clear_sock fileno $self->{device_fd};
86     }
87     }
88    
89     $self->{socket};
90     }
91    
92     sub device {
93     my $self = shift;
94    
95     if (@_) {
96     my $device = shift;
97    
98 root 1.13 # try to load the module if the device nodes don't exist
99     # might be better to handle this via mknod?
100     -b "/dev/nbd0"
101     or system "modprobe nbd >/dev/null 2>&1";
102    
103 root 1.1 if (defined $device) {
104     open my $dev, "+<$device" or croak "$device: $!";
105     $self->{device} = $device;
106     $self->{device_fd} = $dev;
107     } else {
108     for (0..256) {
109     $_ < 256 or croak "unable to find an available nbd device";
110    
111 root 1.12 my $path = "/dev/nbd$_";
112 root 1.6 -e $path or system "mknod", $path, "b", 43, $_;
113 root 1.1 open my $dev, "+<$path" or croak "$device: $!";
114     _set_sock fileno $dev, -1;
115     if ($!{EINVAL}) {
116     $self->{device} = $path;
117     $self->{device_fd} = $dev;
118     last;
119     } elsif ($!{EBUSY}) {
120     next;
121     } else {
122     croak "$path: $!";
123     }
124     }
125     }
126     }
127    
128     $self->{device};
129     }
130    
131     =item $client->disconnect
132    
133 root 1.10 Tries to exit the server by sending a special disconnect message.
134 root 1.1
135     =item $client->clear_queue
136    
137     Clears the request queue, if possible. Should be used before setting a new
138     socket.
139    
140 root 1.11 =item $client->set_timeout ($timeout)
141    
142     Set the request timeout, in seconds.
143    
144 root 1.10 =item $client->set_blocksize ($blksize)
145 root 1.1
146 root 1.11 Set the device block size in bytes, i.e. how big each block is (must be
147     >512, <PAGESIZE and a power of two).
148    
149     Also rounds down the device size to be a multiple of the block size.
150 root 1.1
151 root 1.11 =item $client->set_blocks ($nblocks)
152 root 1.1
153 root 1.11 Set the device size in block units.
154 root 1.1
155 root 1.11 =item $client->set_size ($bytes)
156 root 1.1
157 root 1.11 Set the device size in octet units, will be rounded down to be a multiple
158     of the block size.
159 root 1.1
160     =cut
161    
162     sub disconnect {
163     my $self = shift;
164    
165     _disconnect fileno $self->{device_fd};
166     }
167    
168     sub clear_queue {
169     my $self = shift;
170    
171     _clear_que fileno $self->{device_fd};
172     }
173    
174 root 1.11 sub set_timeout {
175     my $self = shift;
176    
177     _set_timeout fileno $self->{device_fd}, $_[0];
178     }
179    
180 root 1.1 sub set_blocksize {
181     my $self = shift;
182    
183     _set_blksize fileno $self->{device_fd}, $_[0];
184     }
185    
186     sub set_size {
187     my $self = shift;
188    
189     _set_size fileno $self->{device_fd}, $_[0];
190     }
191    
192     sub set_blocks {
193     my $self = shift;
194    
195     _set_size_blocks fileno $self->{device_fd}, $_[0];
196     }
197    
198 root 1.11 sub print_debug {
199     my $self = shift;
200    
201     _print_debug fileno $self->{device_fd};
202     }
203    
204 root 1.1 =item $client->run
205    
206 root 1.11 Closes all file descriptors except the server socket and enters
207     the service loop (waits for read/write requests on the device and
208 root 1.10 forwards them over the given socket). Only returns when somebody calls
209     C<disconnect> or the server is killed.
210 root 1.1
211     =item $pid = $client->run_async
212    
213     Runs the service loop asynchronously and returns the pid of the newly
214     created service process.
215    
216     =item $client->kill_async
217    
218 root 1.2 Kills any running async service. Please note that this also kills the
219     socket, so you need to re-set the socket after this call.
220 root 1.1
221     =cut
222    
223     sub run {
224     my $self = shift;
225 root 1.11
226 root 1.1 _doit fileno $self->{device_fd};
227     }
228    
229     sub run_async {
230     my $self = shift;
231    
232     $self->{pid} = fork;
233 root 1.10
234 root 1.1 defined $self->{pid} or croak "fork: $!";
235 root 1.10 return $self->{pid} if $self->{pid};
236 root 1.1
237 root 1.10 _doit fileno $self->{device_fd}, 1;
238 root 1.1 }
239    
240     sub kill_async {
241     my $self = shift;
242    
243     if (my $pid = delete $self->{pid}) {
244 root 1.3 #_clear_que fileno $self->{device_fd};
245     #_disconnect fileno $self->{device_fd};
246     #_clear_sock fileno $self->{device_fd};
247 root 1.5 # just kill -9 it, seems to be safest (all other ways just oops sooner or later)
248     kill 9, $pid;
249 root 1.1 }
250     }
251    
252     sub DESTROY {
253     my $self = shift;
254    
255     $self->kill_async;
256     }
257    
258     =cut
259    
260     1;
261    
262     =back
263    
264     =head1 AUTHOR
265    
266 root 1.8 Marc Lehmann <schmorp@schmorp.de>
267     http://home.schmorp.de/
268 root 1.1
269     =cut
270