projects
/
linux-2.6-microblaze.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge tag 'nds32-for-linus-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git]
/
drivers
/
block
/
nbd.c
diff --git
a/drivers/block/nbd.c
b/drivers/block/nbd.c
index
3b7083b
..
74a0556
100644
(file)
--- a/
drivers/block/nbd.c
+++ b/
drivers/block/nbd.c
@@
-76,6
+76,7
@@
struct link_dead_args {
#define NBD_HAS_CONFIG_REF 4
#define NBD_BOUND 5
#define NBD_DESTROY_ON_DISCONNECT 6
#define NBD_HAS_CONFIG_REF 4
#define NBD_BOUND 5
#define NBD_DESTROY_ON_DISCONNECT 6
+#define NBD_DISCONNECT_ON_CLOSE 7
struct nbd_config {
u32 flags;
struct nbd_config {
u32 flags;
@@
-138,6
+139,7
@@
static void nbd_config_put(struct nbd_device *nbd);
static void nbd_connect_reply(struct genl_info *info, int index);
static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
static void nbd_dead_link_work(struct work_struct *work);
static void nbd_connect_reply(struct genl_info *info, int index);
static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
static void nbd_dead_link_work(struct work_struct *work);
+static void nbd_disconnect_and_put(struct nbd_device *nbd);
static inline struct device *nbd_to_dev(struct nbd_device *nbd)
{
static inline struct device *nbd_to_dev(struct nbd_device *nbd)
{
@@
-1305,6
+1307,12
@@
out:
static void nbd_release(struct gendisk *disk, fmode_t mode)
{
struct nbd_device *nbd = disk->private_data;
static void nbd_release(struct gendisk *disk, fmode_t mode)
{
struct nbd_device *nbd = disk->private_data;
+ struct block_device *bdev = bdget_disk(disk, 0);
+
+ if (test_bit(NBD_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) &&
+ bdev->bd_openers == 0)
+ nbd_disconnect_and_put(nbd);
+
nbd_config_put(nbd);
nbd_put(nbd);
}
nbd_config_put(nbd);
nbd_put(nbd);
}
@@
-1705,6
+1713,10
@@
again:
&config->runtime_flags);
put_dev = true;
}
&config->runtime_flags);
put_dev = true;
}
+ if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
+ set_bit(NBD_DISCONNECT_ON_CLOSE,
+ &config->runtime_flags);
+ }
}
if (info->attrs[NBD_ATTR_SOCKETS]) {
}
if (info->attrs[NBD_ATTR_SOCKETS]) {
@@
-1749,6
+1761,17
@@
out:
return ret;
}
return ret;
}
+static void nbd_disconnect_and_put(struct nbd_device *nbd)
+{
+ mutex_lock(&nbd->config_lock);
+ nbd_disconnect(nbd);
+ nbd_clear_sock(nbd);
+ mutex_unlock(&nbd->config_lock);
+ if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
+ &nbd->config->runtime_flags))
+ nbd_config_put(nbd);
+}
+
static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
{
struct nbd_device *nbd;
static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
{
struct nbd_device *nbd;
@@
-1781,13
+1804,7
@@
static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
nbd_put(nbd);
return 0;
}
nbd_put(nbd);
return 0;
}
- mutex_lock(&nbd->config_lock);
- nbd_disconnect(nbd);
- nbd_clear_sock(nbd);
- mutex_unlock(&nbd->config_lock);
- if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
- &nbd->config->runtime_flags))
- nbd_config_put(nbd);
+ nbd_disconnect_and_put(nbd);
nbd_config_put(nbd);
nbd_put(nbd);
return 0;
nbd_config_put(nbd);
nbd_put(nbd);
return 0;
@@
-1798,7
+1815,7
@@
static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
struct nbd_device *nbd = NULL;
struct nbd_config *config;
int index;
struct nbd_device *nbd = NULL;
struct nbd_config *config;
int index;
- int ret =
-EINVAL
;
+ int ret =
0
;
bool put_dev = false;
if (!netlink_capable(skb, CAP_SYS_ADMIN))
bool put_dev = false;
if (!netlink_capable(skb, CAP_SYS_ADMIN))
@@
-1838,6
+1855,7
@@
static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
!nbd->task_recv) {
dev_err(nbd_to_dev(nbd),
"not configured, cannot reconfigure\n");
!nbd->task_recv) {
dev_err(nbd_to_dev(nbd),
"not configured, cannot reconfigure\n");
+ ret = -EINVAL;
goto out;
}
goto out;
}
@@
-1862,6
+1880,14
@@
static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
&config->runtime_flags))
refcount_inc(&nbd->refs);
}
&config->runtime_flags))
refcount_inc(&nbd->refs);
}
+
+ if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
+ set_bit(NBD_DISCONNECT_ON_CLOSE,
+ &config->runtime_flags);
+ } else {
+ clear_bit(NBD_DISCONNECT_ON_CLOSE,
+ &config->runtime_flags);
+ }
}
if (info->attrs[NBD_ATTR_SOCKETS]) {
}
if (info->attrs[NBD_ATTR_SOCKETS]) {