* Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
* Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
*
- * (part of code stolen from loop.c)
+ * This file is released under GPLv2 or later.
*
- * 97-3-25 compiled 0-th version, not yet tested it
- * (it did not work, BTW) (later that day) HEY! it works!
- * (bit later) hmm, not that much... 2:00am next day:
- * yes, it works, but it gives something like 50kB/sec
- * 97-4-01 complete rewrite to make it possible for many requests at
- * once to be processed
- * 97-4-11 Making protocol independent of endianity etc.
- * 97-9-13 Cosmetic changes
- * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines
- * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
- * 01-2-27 Fix to store proper blockcount for kernel (calculated using
- * BLOCK_SIZE_BITS, not device blocksize) <aga@permonline.ru>
- * 01-3-11 Make nbd work with new Linux block layer code. It now supports
- * plugging like all the other block devices. Also added in MSG_MORE to
- * reduce number of partial TCP segments sent. <steve@chygwyn.com>
- * 01-12-6 Fix deadlock condition by making queue locks independent of
- * the transmit lock. <steve@chygwyn.com>
- * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes.
- * <Paul.Clements@SteelEye.com> <James.Bottomley@SteelEye.com>
- * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes
- * memory corruption from module removal and possible memory corruption
- * from sending/receiving disk data. <ldl@aros.net>
- * 03-06-23 Cosmetic changes. <ldl@aros.net>
- * 03-06-23 Enhance diagnostics support. <ldl@aros.net>
- * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct.
- * <ldl@aros.net>
- * 03-06-24 Cleanup PARANOIA usage & code. <ldl@aros.net>
- * 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements)
- * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
- * why not: would need access_ok and friends, would share yet another
- * structure with userland
+ * (part of code stolen from loop.c)
*/
#include <linux/major.h>
#include <linux/kernel.h>
#include <net/sock.h>
-#include <linux/devfs_fs_kernel.h>
-
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/types.h>
#define DBG_RX 0x0200
#define DBG_TX 0x0400
static unsigned int debugflags;
-static unsigned int nbds_max = 16;
#endif /* NDEBUG */
+static unsigned int nbds_max = 16;
static struct nbd_device nbd_dev[MAX_NBD];
/*
lo->disk->disk_name, result);
goto harderror;
}
+
+ if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+ printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
+ lo->disk->disk_name,
+ (unsigned long)ntohl(reply.magic));
+ result = -EPROTO;
+ goto harderror;
+ }
+
req = nbd_find_request(lo, reply.handle);
if (unlikely(IS_ERR(req))) {
result = PTR_ERR(req);
goto harderror;
}
- if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
- printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
- lo->disk->disk_name,
- (unsigned long)ntohl(reply.magic));
- result = -EPROTO;
- goto harderror;
- }
if (ntohl(reply.error)) {
printk(KERN_ERR "%s: Other side returned error (%d)\n",
lo->disk->disk_name, ntohl(reply.error));
printk(KERN_ERR "%s: Receive data failed (result %d)\n",
lo->disk->disk_name,
result);
- goto harderror;
+ req->errors++;
+ return req;
}
dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
lo->disk->disk_name, req, bvec->bv_len);
return NULL;
}
+static ssize_t pid_show(struct gendisk *disk, char *page)
+{
+ return sprintf(page, "%ld\n",
+ (long) ((struct nbd_device *)disk->private_data)->pid);
+}
+
+static struct disk_attribute pid_attr = {
+ .attr = { .name = "pid", .mode = S_IRUGO },
+ .show = pid_show,
+};
+
static void nbd_do_it(struct nbd_device *lo)
{
struct request *req;
BUG_ON(lo->magic != LO_MAGIC);
+ lo->pid = current->pid;
+ sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
+
while ((req = nbd_read_stat(lo)) != NULL)
nbd_end_request(req);
+
+ sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
return;
}
struct nbd_device *lo;
blkdev_dequeue_request(req);
- dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
- req->rq_disk->disk_name, req, req->flags);
+ dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
+ req->rq_disk->disk_name, req, req->cmd_type);
- if (!(req->flags & REQ_CMD))
+ if (!blk_fs_request(req))
goto error_out;
lo = req->rq_disk->private_data;
req->errors = 0;
spin_unlock_irq(q->queue_lock);
- down(&lo->tx_lock);
+ mutex_lock(&lo->tx_lock);
if (unlikely(!lo->sock)) {
- up(&lo->tx_lock);
+ mutex_unlock(&lo->tx_lock);
printk(KERN_ERR "%s: Attempted send on closed socket\n",
lo->disk->disk_name);
req->errors++;
}
lo->active_req = NULL;
- up(&lo->tx_lock);
+ mutex_unlock(&lo->tx_lock);
wake_up_all(&lo->active_wq);
spin_lock_irq(q->queue_lock);
switch (cmd) {
case NBD_DISCONNECT:
printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
- sreq.flags = REQ_SPECIAL;
+ sreq.cmd_type = REQ_TYPE_SPECIAL;
nbd_cmd(&sreq) = NBD_CMD_DISC;
/*
* Set these to sane values in case server implementation
case NBD_CLEAR_SOCK:
error = 0;
- down(&lo->tx_lock);
+ mutex_lock(&lo->tx_lock);
lo->sock = NULL;
- up(&lo->tx_lock);
+ mutex_unlock(&lo->tx_lock);
file = lo->file;
lo->file = NULL;
nbd_clear_que(lo);
error = -EINVAL;
file = fget(arg);
if (file) {
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (S_ISSOCK(inode->i_mode)) {
lo->file = file;
lo->sock = SOCKET_I(inode);
* FIXME: This code is duplicated from sys_shutdown, but
* there should be a more generic interface rather than
* calling socket ops directly here */
- down(&lo->tx_lock);
+ mutex_lock(&lo->tx_lock);
if (lo->sock) {
printk(KERN_WARNING "%s: shutting down socket\n",
lo->disk->disk_name);
SEND_SHUTDOWN|RCV_SHUTDOWN);
lo->sock = NULL;
}
- up(&lo->tx_lock);
+ mutex_unlock(&lo->tx_lock);
file = lo->file;
lo->file = NULL;
nbd_clear_que(lo);
int err = -ENOMEM;
int i;
- if (sizeof(struct nbd_request) != 28) {
- printk(KERN_CRIT "nbd: sizeof nbd_request needs to be 28 in order to work!\n" );
- return -EIO;
- }
+ BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
if (nbds_max > MAX_NBD) {
printk(KERN_CRIT "nbd: cannot allocate more than %u nbds; %u requested.\n", MAX_NBD,
printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
- devfs_mk_dir("nbd");
for (i = 0; i < nbds_max; i++) {
struct gendisk *disk = nbd_dev[i].disk;
nbd_dev[i].file = NULL;
nbd_dev[i].flags = 0;
spin_lock_init(&nbd_dev[i].queue_lock);
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
- init_MUTEX(&nbd_dev[i].tx_lock);
+ mutex_init(&nbd_dev[i].tx_lock);
init_waitqueue_head(&nbd_dev[i].active_wq);
nbd_dev[i].blksize = 1024;
nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
disk->private_data = &nbd_dev[i];
disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
sprintf(disk->disk_name, "nbd%d", i);
- sprintf(disk->devfs_name, "nbd/%d", i);
set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */
add_disk(disk);
}
put_disk(disk);
}
}
- devfs_remove("nbd");
unregister_blkdev(NBD_MAJOR, "nbd");
printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
}