@@ -541,7 +541,6 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
541
541
return - ENOENT ;
542
542
543
543
(void ) get_device (& rbd_dev -> dev );
544
- set_device_ro (bdev , rbd_dev -> mapping .read_only );
545
544
546
545
return 0 ;
547
546
}
@@ -559,10 +558,76 @@ static void rbd_release(struct gendisk *disk, fmode_t mode)
559
558
put_device (& rbd_dev -> dev );
560
559
}
561
560
561
+ static int rbd_ioctl_set_ro (struct rbd_device * rbd_dev , unsigned long arg )
562
+ {
563
+ int ret = 0 ;
564
+ int val ;
565
+ bool ro ;
566
+ bool ro_changed = false;
567
+
568
+ /* get_user() may sleep, so call it before taking rbd_dev->lock */
569
+ if (get_user (val , (int __user * )(arg )))
570
+ return - EFAULT ;
571
+
572
+ ro = val ? true : false;
573
+ /* Snapshot doesn't allow to write*/
574
+ if (rbd_dev -> spec -> snap_id != CEPH_NOSNAP && !ro )
575
+ return - EROFS ;
576
+
577
+ spin_lock_irq (& rbd_dev -> lock );
578
+ /* prevent others open this device */
579
+ if (rbd_dev -> open_count > 1 ) {
580
+ ret = - EBUSY ;
581
+ goto out ;
582
+ }
583
+
584
+ if (rbd_dev -> mapping .read_only != ro ) {
585
+ rbd_dev -> mapping .read_only = ro ;
586
+ ro_changed = true;
587
+ }
588
+
589
+ out :
590
+ spin_unlock_irq (& rbd_dev -> lock );
591
+ /* set_disk_ro() may sleep, so call it after releasing rbd_dev->lock */
592
+ if (ret == 0 && ro_changed )
593
+ set_disk_ro (rbd_dev -> disk , ro ? 1 : 0 );
594
+
595
+ return ret ;
596
+ }
597
+
598
+ static int rbd_ioctl (struct block_device * bdev , fmode_t mode ,
599
+ unsigned int cmd , unsigned long arg )
600
+ {
601
+ struct rbd_device * rbd_dev = bdev -> bd_disk -> private_data ;
602
+ int ret = 0 ;
603
+
604
+ switch (cmd ) {
605
+ case BLKROSET :
606
+ ret = rbd_ioctl_set_ro (rbd_dev , arg );
607
+ break ;
608
+ default :
609
+ ret = - ENOTTY ;
610
+ }
611
+
612
+ return ret ;
613
+ }
614
+
615
+ #ifdef CONFIG_COMPAT
616
+ static int rbd_compat_ioctl (struct block_device * bdev , fmode_t mode ,
617
+ unsigned int cmd , unsigned long arg )
618
+ {
619
+ return rbd_ioctl (bdev , mode , cmd , arg );
620
+ }
621
+ #endif /* CONFIG_COMPAT */
622
+
562
623
static const struct block_device_operations rbd_bd_ops = {
563
624
.owner = THIS_MODULE ,
564
625
.open = rbd_open ,
565
626
.release = rbd_release ,
627
+ .ioctl = rbd_ioctl ,
628
+ #ifdef CONFIG_COMPAT
629
+ .compat_ioctl = rbd_compat_ioctl ,
630
+ #endif
566
631
};
567
632
568
633
/*
@@ -1382,6 +1447,13 @@ static void rbd_obj_request_put(struct rbd_obj_request *obj_request)
1382
1447
kref_put (& obj_request -> kref , rbd_obj_request_destroy );
1383
1448
}
1384
1449
1450
+ static void rbd_img_request_get (struct rbd_img_request * img_request )
1451
+ {
1452
+ dout ("%s: img %p (was %d)\n" , __func__ , img_request ,
1453
+ atomic_read (& img_request -> kref .refcount ));
1454
+ kref_get (& img_request -> kref );
1455
+ }
1456
+
1385
1457
static bool img_request_child_test (struct rbd_img_request * img_request );
1386
1458
static void rbd_parent_request_destroy (struct kref * kref );
1387
1459
static void rbd_img_request_destroy (struct kref * kref );
@@ -2142,6 +2214,7 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_request)
2142
2214
img_request -> next_completion = which ;
2143
2215
out :
2144
2216
spin_unlock_irq (& img_request -> completion_lock );
2217
+ rbd_img_request_put (img_request );
2145
2218
2146
2219
if (!more )
2147
2220
rbd_img_request_complete (img_request );
@@ -2242,6 +2315,7 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
2242
2315
goto out_unwind ;
2243
2316
obj_request -> osd_req = osd_req ;
2244
2317
obj_request -> callback = rbd_img_obj_callback ;
2318
+ rbd_img_request_get (img_request );
2245
2319
2246
2320
if (write_request ) {
2247
2321
osd_req_op_alloc_hint_init (osd_req , which ,
@@ -2872,56 +2946,55 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
2872
2946
}
2873
2947
2874
2948
/*
2875
- * Request sync osd watch/unwatch. The value of "start" determines
2876
- * whether a watch request is being initiated or torn down.
2949
+ * Initiate a watch request, synchronously.
2877
2950
*/
2878
- static int __rbd_dev_header_watch_sync (struct rbd_device * rbd_dev , bool start )
2951
+ static int rbd_dev_header_watch_sync (struct rbd_device * rbd_dev )
2879
2952
{
2880
2953
struct ceph_osd_client * osdc = & rbd_dev -> rbd_client -> client -> osdc ;
2881
2954
struct rbd_obj_request * obj_request ;
2882
2955
int ret ;
2883
2956
2884
- rbd_assert (start ^ ! !rbd_dev -> watch_event );
2885
- rbd_assert (start ^ ! !rbd_dev -> watch_request );
2957
+ rbd_assert (!rbd_dev -> watch_event );
2958
+ rbd_assert (!rbd_dev -> watch_request );
2886
2959
2887
- if (start ) {
2888
- ret = ceph_osdc_create_event (osdc , rbd_watch_cb , rbd_dev ,
2889
- & rbd_dev -> watch_event );
2890
- if (ret < 0 )
2891
- return ret ;
2892
- rbd_assert (rbd_dev -> watch_event != NULL );
2893
- }
2960
+ ret = ceph_osdc_create_event (osdc , rbd_watch_cb , rbd_dev ,
2961
+ & rbd_dev -> watch_event );
2962
+ if (ret < 0 )
2963
+ return ret ;
2964
+
2965
+ rbd_assert (rbd_dev -> watch_event );
2894
2966
2895
- ret = - ENOMEM ;
2896
2967
obj_request = rbd_obj_request_create (rbd_dev -> header_name , 0 , 0 ,
2897
- OBJ_REQUEST_NODATA );
2898
- if (!obj_request )
2968
+ OBJ_REQUEST_NODATA );
2969
+ if (!obj_request ) {
2970
+ ret = - ENOMEM ;
2899
2971
goto out_cancel ;
2972
+ }
2900
2973
2901
2974
obj_request -> osd_req = rbd_osd_req_create (rbd_dev , true, 1 ,
2902
2975
obj_request );
2903
- if (!obj_request -> osd_req )
2904
- goto out_cancel ;
2976
+ if (!obj_request -> osd_req ) {
2977
+ ret = - ENOMEM ;
2978
+ goto out_put ;
2979
+ }
2905
2980
2906
- if (start )
2907
- ceph_osdc_set_request_linger (osdc , obj_request -> osd_req );
2908
- else
2909
- ceph_osdc_unregister_linger_request (osdc ,
2910
- rbd_dev -> watch_request -> osd_req );
2981
+ ceph_osdc_set_request_linger (osdc , obj_request -> osd_req );
2911
2982
2912
2983
osd_req_op_watch_init (obj_request -> osd_req , 0 , CEPH_OSD_OP_WATCH ,
2913
- rbd_dev -> watch_event -> cookie , 0 , start ? 1 : 0 );
2984
+ rbd_dev -> watch_event -> cookie , 0 , 1 );
2914
2985
rbd_osd_req_format_write (obj_request );
2915
2986
2916
2987
ret = rbd_obj_request_submit (osdc , obj_request );
2917
2988
if (ret )
2918
- goto out_cancel ;
2989
+ goto out_linger ;
2990
+
2919
2991
ret = rbd_obj_request_wait (obj_request );
2920
2992
if (ret )
2921
- goto out_cancel ;
2993
+ goto out_linger ;
2994
+
2922
2995
ret = obj_request -> result ;
2923
2996
if (ret )
2924
- goto out_cancel ;
2997
+ goto out_linger ;
2925
2998
2926
2999
/*
2927
3000
* A watch request is set to linger, so the underlying osd
@@ -2931,36 +3004,84 @@ static int __rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, bool start)
2931
3004
* it. We'll drop that reference (below) after we've
2932
3005
* unregistered it.
2933
3006
*/
2934
- if (start ) {
2935
- rbd_dev -> watch_request = obj_request ;
3007
+ rbd_dev -> watch_request = obj_request ;
2936
3008
2937
- return 0 ;
3009
+ return 0 ;
3010
+
3011
+ out_linger :
3012
+ ceph_osdc_unregister_linger_request (osdc , obj_request -> osd_req );
3013
+ out_put :
3014
+ rbd_obj_request_put (obj_request );
3015
+ out_cancel :
3016
+ ceph_osdc_cancel_event (rbd_dev -> watch_event );
3017
+ rbd_dev -> watch_event = NULL ;
3018
+
3019
+ return ret ;
3020
+ }
3021
+
3022
+ /*
3023
+ * Tear down a watch request, synchronously.
3024
+ */
3025
+ static int __rbd_dev_header_unwatch_sync (struct rbd_device * rbd_dev )
3026
+ {
3027
+ struct ceph_osd_client * osdc = & rbd_dev -> rbd_client -> client -> osdc ;
3028
+ struct rbd_obj_request * obj_request ;
3029
+ int ret ;
3030
+
3031
+ rbd_assert (rbd_dev -> watch_event );
3032
+ rbd_assert (rbd_dev -> watch_request );
3033
+
3034
+ obj_request = rbd_obj_request_create (rbd_dev -> header_name , 0 , 0 ,
3035
+ OBJ_REQUEST_NODATA );
3036
+ if (!obj_request ) {
3037
+ ret = - ENOMEM ;
3038
+ goto out_cancel ;
3039
+ }
3040
+
3041
+ obj_request -> osd_req = rbd_osd_req_create (rbd_dev , true, 1 ,
3042
+ obj_request );
3043
+ if (!obj_request -> osd_req ) {
3044
+ ret = - ENOMEM ;
3045
+ goto out_put ;
2938
3046
}
2939
3047
3048
+ osd_req_op_watch_init (obj_request -> osd_req , 0 , CEPH_OSD_OP_WATCH ,
3049
+ rbd_dev -> watch_event -> cookie , 0 , 0 );
3050
+ rbd_osd_req_format_write (obj_request );
3051
+
3052
+ ret = rbd_obj_request_submit (osdc , obj_request );
3053
+ if (ret )
3054
+ goto out_put ;
3055
+
3056
+ ret = rbd_obj_request_wait (obj_request );
3057
+ if (ret )
3058
+ goto out_put ;
3059
+
3060
+ ret = obj_request -> result ;
3061
+ if (ret )
3062
+ goto out_put ;
3063
+
2940
3064
/* We have successfully torn down the watch request */
2941
3065
3066
+ ceph_osdc_unregister_linger_request (osdc ,
3067
+ rbd_dev -> watch_request -> osd_req );
2942
3068
rbd_obj_request_put (rbd_dev -> watch_request );
2943
3069
rbd_dev -> watch_request = NULL ;
3070
+
3071
+ out_put :
3072
+ rbd_obj_request_put (obj_request );
2944
3073
out_cancel :
2945
- /* Cancel the event if we're tearing down, or on error */
2946
3074
ceph_osdc_cancel_event (rbd_dev -> watch_event );
2947
3075
rbd_dev -> watch_event = NULL ;
2948
- if (obj_request )
2949
- rbd_obj_request_put (obj_request );
2950
3076
2951
3077
return ret ;
2952
3078
}
2953
3079
2954
- static int rbd_dev_header_watch_sync (struct rbd_device * rbd_dev )
2955
- {
2956
- return __rbd_dev_header_watch_sync (rbd_dev , true);
2957
- }
2958
-
2959
3080
static void rbd_dev_header_unwatch_sync (struct rbd_device * rbd_dev )
2960
3081
{
2961
3082
int ret ;
2962
3083
2963
- ret = __rbd_dev_header_watch_sync (rbd_dev , false );
3084
+ ret = __rbd_dev_header_unwatch_sync (rbd_dev );
2964
3085
if (ret ) {
2965
3086
rbd_warn (rbd_dev , "unable to tear down watch request: %d\n" ,
2966
3087
ret );
@@ -3058,7 +3179,6 @@ static void rbd_request_fn(struct request_queue *q)
3058
3179
__releases (q - > queue_lock ) __acquires (q - > queue_lock )
3059
3180
{
3060
3181
struct rbd_device * rbd_dev = q -> queuedata ;
3061
- bool read_only = rbd_dev -> mapping .read_only ;
3062
3182
struct request * rq ;
3063
3183
int result ;
3064
3184
@@ -3094,7 +3214,7 @@ static void rbd_request_fn(struct request_queue *q)
3094
3214
3095
3215
if (write_request ) {
3096
3216
result = - EROFS ;
3097
- if (read_only )
3217
+ if (rbd_dev -> mapping . read_only )
3098
3218
goto end_request ;
3099
3219
rbd_assert (rbd_dev -> spec -> snap_id == CEPH_NOSNAP );
3100
3220
}
@@ -4682,6 +4802,38 @@ static int rbd_add_parse_args(const char *buf,
4682
4802
return ret ;
4683
4803
}
4684
4804
4805
+ /*
4806
+ * Return pool id (>= 0) or a negative error code.
4807
+ */
4808
+ static int rbd_add_get_pool_id (struct rbd_client * rbdc , const char * pool_name )
4809
+ {
4810
+ u64 newest_epoch ;
4811
+ unsigned long timeout = rbdc -> client -> options -> mount_timeout * HZ ;
4812
+ int tries = 0 ;
4813
+ int ret ;
4814
+
4815
+ again :
4816
+ ret = ceph_pg_poolid_by_name (rbdc -> client -> osdc .osdmap , pool_name );
4817
+ if (ret == - ENOENT && tries ++ < 1 ) {
4818
+ ret = ceph_monc_do_get_version (& rbdc -> client -> monc , "osdmap" ,
4819
+ & newest_epoch );
4820
+ if (ret < 0 )
4821
+ return ret ;
4822
+
4823
+ if (rbdc -> client -> osdc .osdmap -> epoch < newest_epoch ) {
4824
+ ceph_monc_request_next_osdmap (& rbdc -> client -> monc );
4825
+ (void ) ceph_monc_wait_osdmap (& rbdc -> client -> monc ,
4826
+ newest_epoch , timeout );
4827
+ goto again ;
4828
+ } else {
4829
+ /* the osdmap we have is new enough */
4830
+ return - ENOENT ;
4831
+ }
4832
+ }
4833
+
4834
+ return ret ;
4835
+ }
4836
+
4685
4837
/*
4686
4838
* An rbd format 2 image has a unique identifier, distinct from the
4687
4839
* name given to it by the user. Internally, that identifier is
@@ -4752,7 +4904,7 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
4752
4904
4753
4905
image_id = ceph_extract_encoded_string (& p , p + ret ,
4754
4906
NULL , GFP_NOIO );
4755
- ret = IS_ERR (image_id ) ? PTR_ERR ( image_id ) : 0 ;
4907
+ ret = PTR_ERR_OR_ZERO (image_id );
4756
4908
if (!ret )
4757
4909
rbd_dev -> image_format = 2 ;
4758
4910
} else {
@@ -4907,6 +5059,7 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
4907
5059
if (ret )
4908
5060
goto err_out_disk ;
4909
5061
set_capacity (rbd_dev -> disk , rbd_dev -> mapping .size / SECTOR_SIZE );
5062
+ set_disk_ro (rbd_dev -> disk , rbd_dev -> mapping .read_only );
4910
5063
4911
5064
ret = rbd_bus_add_dev (rbd_dev );
4912
5065
if (ret )
@@ -5053,7 +5206,6 @@ static ssize_t do_rbd_add(struct bus_type *bus,
5053
5206
struct rbd_options * rbd_opts = NULL ;
5054
5207
struct rbd_spec * spec = NULL ;
5055
5208
struct rbd_client * rbdc ;
5056
- struct ceph_osd_client * osdc ;
5057
5209
bool read_only ;
5058
5210
int rc = - ENOMEM ;
5059
5211
@@ -5075,8 +5227,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
5075
5227
}
5076
5228
5077
5229
/* pick the pool */
5078
- osdc = & rbdc -> client -> osdc ;
5079
- rc = ceph_pg_poolid_by_name (osdc -> osdmap , spec -> pool_name );
5230
+ rc = rbd_add_get_pool_id (rbdc , spec -> pool_name );
5080
5231
if (rc < 0 )
5081
5232
goto err_out_client ;
5082
5233
spec -> pool_id = (u64 )rc ;
@@ -5387,6 +5538,7 @@ static int __init rbd_init(void)
5387
5538
5388
5539
static void __exit rbd_exit (void )
5389
5540
{
5541
+ ida_destroy (& rbd_dev_id_ida );
5390
5542
rbd_sysfs_cleanup ();
5391
5543
if (single_major )
5392
5544
unregister_blkdev (rbd_major , RBD_DRV_NAME );
0 commit comments