nbd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:13k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Network block device - make block devices work over TCP
  3.  *
  4.  * Note that you can not swap over this thing, yet. Seems to work but
  5.  * deadlocks sometimes - you can not swap over TCP in general.
  6.  * 
  7.  * Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
  8.  * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
  9.  *
  10.  * (part of code stolen from loop.c)
  11.  *
  12.  * 97-3-25 compiled 0-th version, not yet tested it 
  13.  *   (it did not work, BTW) (later that day) HEY! it works!
  14.  *   (bit later) hmm, not that much... 2:00am next day:
  15.  *   yes, it works, but it gives something like 50kB/sec
  16.  * 97-4-01 complete rewrite to make it possible for many requests at 
  17.  *   once to be processed
  18.  * 97-4-11 Making protocol independent of endianity etc.
  19.  * 97-9-13 Cosmetic changes
  20.  * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines
  21.  * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
  22.  * 01-2-27 Fix to store proper blockcount for kernel (calculated using
  23.  *   BLOCK_SIZE_BITS, not device blocksize) <aga@permonline.ru>
  24.  * 01-3-11 Make nbd work with new Linux block layer code. It now supports
  25.  *   plugging like all the other block devices. Also added in MSG_MORE to
  26.  *   reduce number of partial TCP segments sent. <steve@chygwyn.com>
  27.  * 01-12-6 Fix deadlock condition by making queue locks independant of
  28.  *   the transmit lock. <steve@chygwyn.com>
  29.  *
  30.  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  31.  * why not: would need verify_area and friends, would share yet another 
  32.  *          structure with userland
  33.  */
  34. #define PARANOIA
  35. #include <linux/major.h>
  36. #include <linux/module.h>
  37. #include <linux/init.h>
  38. #include <linux/sched.h>
  39. #include <linux/fs.h>
  40. #include <linux/stat.h>
  41. #include <linux/errno.h>
  42. #include <linux/file.h>
  43. #include <linux/ioctl.h>
  44. #include <net/sock.h>
  45. #include <linux/devfs_fs_kernel.h>
  46. #include <asm/uaccess.h>
  47. #include <asm/types.h>
  48. #define MAJOR_NR NBD_MAJOR
  49. #include <linux/nbd.h>
  50. #define LO_MAGIC 0x68797548
  51. static int nbd_blksizes[MAX_NBD];
  52. static int nbd_blksize_bits[MAX_NBD];
  53. static int nbd_sizes[MAX_NBD];
  54. static u64 nbd_bytesizes[MAX_NBD];
  55. static struct nbd_device nbd_dev[MAX_NBD];
  56. static devfs_handle_t devfs_handle;
  57. #define DEBUG( s )
  58. /* #define DEBUG( s ) printk( s ) 
  59.  */
  60. #ifdef PARANOIA
  61. static int requests_in;
  62. static int requests_out;
  63. #endif
  64. static int nbd_open(struct inode *inode, struct file *file)
  65. {
  66. int dev;
  67. if (!inode)
  68. return -EINVAL;
  69. dev = MINOR(inode->i_rdev);
  70. if (dev >= MAX_NBD)
  71. return -ENODEV;
  72. nbd_dev[dev].refcnt++;
  73. return 0;
  74. }
  75. /*
  76.  *  Send or receive packet.
  77.  */
  78. static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags)
  79. {
  80. mm_segment_t oldfs;
  81. int result;
  82. struct msghdr msg;
  83. struct iovec iov;
  84. unsigned long flags;
  85. sigset_t oldset;
  86. oldfs = get_fs();
  87. set_fs(get_ds());
  88. spin_lock_irqsave(&current->sigmask_lock, flags);
  89. oldset = current->blocked;
  90. sigfillset(&current->blocked);
  91. recalc_sigpending(current);
  92. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  93. do {
  94. sock->sk->allocation = GFP_NOIO;
  95. iov.iov_base = buf;
  96. iov.iov_len = size;
  97. msg.msg_name = NULL;
  98. msg.msg_namelen = 0;
  99. msg.msg_iov = &iov;
  100. msg.msg_iovlen = 1;
  101. msg.msg_control = NULL;
  102. msg.msg_controllen = 0;
  103. msg.msg_namelen = 0;
  104. msg.msg_flags = msg_flags | MSG_NOSIGNAL;
  105. if (send)
  106. result = sock_sendmsg(sock, &msg, size);
  107. else
  108. result = sock_recvmsg(sock, &msg, size, 0);
  109. if (result <= 0) {
  110. #ifdef PARANOIA
  111. printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.n",
  112.        send ? "send" : "receive", (long) sock, (long) buf, size, result);
  113. #endif
  114. break;
  115. }
  116. size -= result;
  117. buf += result;
  118. } while (size > 0);
  119. spin_lock_irqsave(&current->sigmask_lock, flags);
  120. current->blocked = oldset;
  121. recalc_sigpending(current);
  122. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  123. set_fs(oldfs);
  124. return result;
  125. }
  126. #define FAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)n", result ); goto error_out; }
  127. void nbd_send_req(struct nbd_device *lo, struct request *req)
  128. {
  129. int result;
  130. struct nbd_request request;
  131. unsigned long size = req->nr_sectors << 9;
  132. struct socket *sock = lo->sock;
  133. DEBUG("NBD: sending control, ");
  134. request.magic = htonl(NBD_REQUEST_MAGIC);
  135. request.type = htonl(req->cmd);
  136. request.from = cpu_to_be64( (u64) req->sector << 9);
  137. request.len = htonl(size);
  138. memcpy(request.handle, &req, sizeof(req));
  139. down(&lo->tx_lock);
  140. result = nbd_xmit(1, sock, (char *) &request, sizeof(request), req->cmd == WRITE ? MSG_MORE : 0);
  141. if (result <= 0)
  142. FAIL("Sendmsg failed for control.");
  143. if (req->cmd == WRITE) {
  144. struct buffer_head *bh = req->bh;
  145. DEBUG("data, ");
  146. do {
  147. result = nbd_xmit(1, sock, bh->b_data, bh->b_size, bh->b_reqnext == NULL ? 0 : MSG_MORE);
  148. if (result <= 0)
  149. FAIL("Send data failed.");
  150. bh = bh->b_reqnext;
  151. } while(bh);
  152. }
  153. up(&lo->tx_lock);
  154. return;
  155. error_out:
  156. up(&lo->tx_lock);
  157. req->errors++;
  158. }
  159. static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
  160. {
  161. struct request *req;
  162. struct list_head *tmp;
  163. struct request *xreq;
  164. memcpy(&xreq, handle, sizeof(xreq));
  165. spin_lock(&lo->queue_lock);
  166. list_for_each(tmp, &lo->queue_head) {
  167. req = list_entry(tmp, struct request, queue);
  168. if (req != xreq)
  169. continue;
  170. list_del(&req->queue);
  171. spin_unlock(&lo->queue_lock);
  172. return req;
  173. }
  174. spin_unlock(&lo->queue_lock);
  175. return NULL;
  176. }
  177. #define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)n", result ); lo->harderror = result; return NULL; }
  178. struct request *nbd_read_stat(struct nbd_device *lo)
  179. /* NULL returned = something went wrong, inform userspace       */ 
  180. {
  181. int result;
  182. struct nbd_reply reply;
  183. struct request *req;
  184. DEBUG("reading control, ");
  185. reply.magic = 0;
  186. result = nbd_xmit(0, lo->sock, (char *) &reply, sizeof(reply), MSG_WAITALL);
  187. if (result <= 0)
  188. HARDFAIL("Recv control failed.");
  189. req = nbd_find_request(lo, reply.handle);
  190. if (req == NULL)
  191. HARDFAIL("Unexpected reply");
  192. DEBUG("ok, ");
  193. if (ntohl(reply.magic) != NBD_REPLY_MAGIC)
  194. HARDFAIL("Not enough magic.");
  195. if (ntohl(reply.error))
  196. FAIL("Other side returned error.");
  197. if (req->cmd == READ) {
  198. struct buffer_head *bh = req->bh;
  199. DEBUG("data, ");
  200. do {
  201. result = nbd_xmit(0, lo->sock, bh->b_data, bh->b_size, MSG_WAITALL);
  202. if (result <= 0)
  203. HARDFAIL("Recv data failed.");
  204. bh = bh->b_reqnext;
  205. } while(bh);
  206. }
  207. DEBUG("done.n");
  208. return req;
  209. /* Can we get here? Yes, if other side returns error */
  210.       error_out:
  211. req->errors++;
  212. return req;
  213. }
  214. void nbd_do_it(struct nbd_device *lo)
  215. {
  216. struct request *req;
  217. while (1) {
  218. req = nbd_read_stat(lo);
  219. if (!req) {
  220. printk(KERN_ALERT "req should never be nulln" );
  221. goto out;
  222. }
  223. #ifdef PARANOIA
  224. if (lo != &nbd_dev[MINOR(req->rq_dev)]) {
  225. printk(KERN_ALERT "NBD: request corrupted!n");
  226. continue;
  227. }
  228. if (lo->magic != LO_MAGIC) {
  229. printk(KERN_ALERT "NBD: nbd_dev[] corrupted: Not enough magicn");
  230. goto out;
  231. }
  232. #endif
  233. nbd_end_request(req);
  234. }
  235.  out:
  236. return;
  237. }
  238. void nbd_clear_que(struct nbd_device *lo)
  239. {
  240. struct request *req;
  241. #ifdef PARANOIA
  242. if (lo->magic != LO_MAGIC) {
  243. printk(KERN_ERR "NBD: nbd_dev[] corrupted: Not enough magic when clearing!n");
  244. return;
  245. }
  246. #endif
  247. do {
  248. req = NULL;
  249. spin_lock(&lo->queue_lock);
  250. if (!list_empty(&lo->queue_head)) {
  251. req = list_entry(lo->queue_head.next, struct request, queue);
  252. list_del(&req->queue);
  253. }
  254. spin_unlock(&lo->queue_lock);
  255. if (req) {
  256. req->errors++;
  257. nbd_end_request(req);
  258. }
  259. } while(req);
  260. }
  261. /*
  262.  * We always wait for result of write, for now. It would be nice to make it optional
  263.  * in future
  264.  * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK)) 
  265.  *   { printk( "Warning: Ignoring result!n"); nbd_end_request( req ); }
  266.  */
  267. #undef FAIL
  268. #define FAIL( s ) { printk( KERN_ERR "NBD, minor %d: " s "n", dev ); goto error_out; }
  269. static void do_nbd_request(request_queue_t * q)
  270. {
  271. struct request *req;
  272. int dev = 0;
  273. struct nbd_device *lo;
  274. while (!QUEUE_EMPTY) {
  275. req = CURRENT;
  276. #ifdef PARANOIA
  277. if (!req)
  278. FAIL("que not empty but no request?");
  279. #endif
  280. dev = MINOR(req->rq_dev);
  281. #ifdef PARANOIA
  282. if (dev >= MAX_NBD)
  283. FAIL("Minor too big."); /* Probably can not happen */
  284. #endif
  285. lo = &nbd_dev[dev];
  286. if (!lo->file)
  287. FAIL("Request when not-ready.");
  288. if ((req->cmd == WRITE) && (lo->flags & NBD_READ_ONLY))
  289. FAIL("Write on read-only");
  290. #ifdef PARANOIA
  291. if (lo->magic != LO_MAGIC)
  292. FAIL("nbd[] is not magical!");
  293. requests_in++;
  294. #endif
  295. req->errors = 0;
  296. blkdev_dequeue_request(req);
  297. spin_unlock_irq(&io_request_lock);
  298. spin_lock(&lo->queue_lock);
  299. list_add_tail(&req->queue, &lo->queue_head);
  300. spin_unlock(&lo->queue_lock);
  301. nbd_send_req(lo, req);
  302. spin_lock_irq(&io_request_lock);
  303. continue;
  304.       error_out:
  305. req->errors++;
  306. blkdev_dequeue_request(req);
  307. spin_unlock(&io_request_lock);
  308. nbd_end_request(req);
  309. spin_lock(&io_request_lock);
  310. }
  311. return;
  312. }
  313. static int nbd_ioctl(struct inode *inode, struct file *file,
  314.      unsigned int cmd, unsigned long arg)
  315. {
  316. struct nbd_device *lo;
  317. int dev, error, temp;
  318. struct request sreq ;
  319. /* Anyone capable of this syscall can do *real bad* things */
  320. if (!capable(CAP_SYS_ADMIN))
  321. return -EPERM;
  322. if (!inode)
  323. return -EINVAL;
  324. dev = MINOR(inode->i_rdev);
  325. if (dev >= MAX_NBD)
  326. return -ENODEV;
  327. lo = &nbd_dev[dev];
  328. switch (cmd) {
  329. case NBD_DISCONNECT:
  330.         printk("NBD_DISCONNECTn");
  331.                 sreq.cmd=2 ; /* shutdown command */
  332.                 if (!lo->sock) return -EINVAL;
  333.                 nbd_send_req(lo, &sreq);
  334.                 return 0 ;
  335.  
  336. case NBD_CLEAR_SOCK:
  337. nbd_clear_que(lo);
  338. spin_lock(&lo->queue_lock);
  339. if (!list_empty(&lo->queue_head)) {
  340. spin_unlock(&lo->queue_lock);
  341. printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.n");
  342. return -EBUSY;
  343. }
  344. spin_unlock(&lo->queue_lock);
  345. file = lo->file;
  346. if (!file)
  347. return -EINVAL;
  348. lo->file = NULL;
  349. lo->sock = NULL;
  350. fput(file);
  351. return 0;
  352. case NBD_SET_SOCK:
  353. if (lo->file)
  354. return -EBUSY;
  355. error = -EINVAL;
  356. file = fget(arg);
  357. if (file) {
  358. inode = file->f_dentry->d_inode;
  359. /* N.B. Should verify that it's a socket */
  360. lo->file = file;
  361. lo->sock = &inode->u.socket_i;
  362. error = 0;
  363. }
  364. return error;
  365. case NBD_SET_BLKSIZE:
  366. if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE))
  367. return -EINVAL;
  368. nbd_blksizes[dev] = arg;
  369. temp = arg >> 9;
  370. nbd_blksize_bits[dev] = 9;
  371. while (temp > 1) {
  372. nbd_blksize_bits[dev]++;
  373. temp >>= 1;
  374. }
  375. nbd_bytesizes[dev] &= ~(nbd_blksizes[dev]-1); 
  376. nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS;
  377. return 0;
  378. case NBD_SET_SIZE:
  379. nbd_bytesizes[dev] = arg & ~(nbd_blksizes[dev]-1); 
  380. nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS;
  381. return 0;
  382. case NBD_SET_SIZE_BLOCKS:
  383. nbd_bytesizes[dev] = ((u64) arg) << nbd_blksize_bits[dev]; 
  384. nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS;
  385. return 0;
  386. case NBD_DO_IT:
  387. if (!lo->file)
  388. return -EINVAL;
  389. nbd_do_it(lo);
  390. return lo->harderror;
  391. case NBD_CLEAR_QUE:
  392. nbd_clear_que(lo);
  393. return 0;
  394. #ifdef PARANOIA
  395. case NBD_PRINT_DEBUG:
  396. printk(KERN_INFO "NBD device %d: next = %p, prev = %p. Global: in %d, out %dn",
  397.        dev, lo->queue_head.next, lo->queue_head.prev, requests_in, requests_out);
  398. return 0;
  399. #endif
  400. case BLKGETSIZE:
  401. return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg);
  402. case BLKGETSIZE64:
  403. return put_user((u64)nbd_bytesizes[dev], (u64 *) arg);
  404. }
  405. return -EINVAL;
  406. }
  407. static int nbd_release(struct inode *inode, struct file *file)
  408. {
  409. struct nbd_device *lo;
  410. int dev;
  411. if (!inode)
  412. return -ENODEV;
  413. dev = MINOR(inode->i_rdev);
  414. if (dev >= MAX_NBD)
  415. return -ENODEV;
  416. lo = &nbd_dev[dev];
  417. if (lo->refcnt <= 0)
  418. printk(KERN_ALERT "nbd_release: refcount(%d) <= 0n", lo->refcnt);
  419. lo->refcnt--;
  420. /* N.B. Doesn't lo->file need an fput?? */
  421. return 0;
  422. }
  423. static struct block_device_operations nbd_fops =
  424. {
  425. owner: THIS_MODULE,
  426. open: nbd_open,
  427. release: nbd_release,
  428. ioctl: nbd_ioctl,
  429. };
  430. /*
  431.  * And here should be modules and kernel interface 
  432.  *  (Just smiley confuses emacs :-)
  433.  */
  434. static int __init nbd_init(void)
  435. {
  436. int i;
  437. if (sizeof(struct nbd_request) != 28) {
  438. printk(KERN_CRIT "Sizeof nbd_request needs to be 28 in order to work!n" );
  439. return -EIO;
  440. }
  441. if (register_blkdev(MAJOR_NR, "nbd", &nbd_fops)) {
  442. printk("Unable to get major number %d for NBDn",
  443.        MAJOR_NR);
  444. return -EIO;
  445. }
  446. #ifdef MODULE
  447. printk("nbd: registered device at major %dn", MAJOR_NR);
  448. #endif
  449. blksize_size[MAJOR_NR] = nbd_blksizes;
  450. blk_size[MAJOR_NR] = nbd_sizes;
  451. blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
  452. blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
  453. for (i = 0; i < MAX_NBD; i++) {
  454. nbd_dev[i].refcnt = 0;
  455. nbd_dev[i].file = NULL;
  456. nbd_dev[i].magic = LO_MAGIC;
  457. nbd_dev[i].flags = 0;
  458. spin_lock_init(&nbd_dev[i].queue_lock);
  459. INIT_LIST_HEAD(&nbd_dev[i].queue_head);
  460. init_MUTEX(&nbd_dev[i].tx_lock);
  461. nbd_blksizes[i] = 1024;
  462. nbd_blksize_bits[i] = 10;
  463. nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
  464. nbd_sizes[i] = nbd_bytesizes[i] >> BLOCK_SIZE_BITS;
  465. register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &nbd_fops,
  466. nbd_bytesizes[i]>>9);
  467. }
  468. devfs_handle = devfs_mk_dir (NULL, "nbd", NULL);
  469. devfs_register_series (devfs_handle, "%u", MAX_NBD,
  470.        DEVFS_FL_DEFAULT, MAJOR_NR, 0,
  471.        S_IFBLK | S_IRUSR | S_IWUSR,
  472.        &nbd_fops, NULL);
  473. return 0;
  474. }
  475. static void __exit nbd_cleanup(void)
  476. {
  477. devfs_unregister (devfs_handle);
  478. blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
  479. if (unregister_blkdev(MAJOR_NR, "nbd") != 0)
  480. printk("nbd: cleanup_module failedn");
  481. else
  482. printk("nbd: module cleaned up.n");
  483. }
  484. module_init(nbd_init);
  485. module_exit(nbd_cleanup);
  486. MODULE_DESCRIPTION("Network Block Device");
  487. MODULE_LICENSE("GPL");