@@ -836,33 +836,153 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
836
836
return error ;
837
837
}
838
838
839
- static struct dentry * get_default_root (struct super_block * sb ,
840
- u64 subvol_objectid )
839
+ static char * get_subvol_name_from_objectid (struct btrfs_fs_info * fs_info ,
840
+ u64 subvol_objectid )
841
841
{
842
- struct btrfs_fs_info * fs_info = btrfs_sb (sb );
843
842
struct btrfs_root * root = fs_info -> tree_root ;
844
- struct btrfs_root * new_root ;
845
- struct btrfs_dir_item * di ;
846
- struct btrfs_path * path ;
847
- struct btrfs_key location ;
848
- struct inode * inode ;
849
- u64 dir_id ;
850
- int new = 0 ;
843
+ struct btrfs_root * fs_root ;
844
+ struct btrfs_root_ref * root_ref ;
845
+ struct btrfs_inode_ref * inode_ref ;
846
+ struct btrfs_key key ;
847
+ struct btrfs_path * path = NULL ;
848
+ char * name = NULL , * ptr ;
849
+ u64 dirid ;
850
+ int len ;
851
+ int ret ;
852
+
853
+ path = btrfs_alloc_path ();
854
+ if (!path ) {
855
+ ret = - ENOMEM ;
856
+ goto err ;
857
+ }
858
+ path -> leave_spinning = 1 ;
859
+
860
+ name = kmalloc (PATH_MAX , GFP_NOFS );
861
+ if (!name ) {
862
+ ret = - ENOMEM ;
863
+ goto err ;
864
+ }
865
+ ptr = name + PATH_MAX - 1 ;
866
+ ptr [0 ] = '\0' ;
851
867
852
868
/*
853
- * We have a specific subvol we want to mount, just setup location and
854
- * go look up the root .
869
+ * Walk up the subvolume trees in the tree of tree roots by root
870
+ * backrefs until we hit the top-level subvolume .
855
871
*/
856
- if (subvol_objectid ) {
857
- location .objectid = subvol_objectid ;
858
- location .type = BTRFS_ROOT_ITEM_KEY ;
859
- location .offset = (u64 )- 1 ;
860
- goto find_root ;
872
+ while (subvol_objectid != BTRFS_FS_TREE_OBJECTID ) {
873
+ key .objectid = subvol_objectid ;
874
+ key .type = BTRFS_ROOT_BACKREF_KEY ;
875
+ key .offset = (u64 )- 1 ;
876
+
877
+ ret = btrfs_search_slot (NULL , root , & key , path , 0 , 0 );
878
+ if (ret < 0 ) {
879
+ goto err ;
880
+ } else if (ret > 0 ) {
881
+ ret = btrfs_previous_item (root , path , subvol_objectid ,
882
+ BTRFS_ROOT_BACKREF_KEY );
883
+ if (ret < 0 ) {
884
+ goto err ;
885
+ } else if (ret > 0 ) {
886
+ ret = - ENOENT ;
887
+ goto err ;
888
+ }
889
+ }
890
+
891
+ btrfs_item_key_to_cpu (path -> nodes [0 ], & key , path -> slots [0 ]);
892
+ subvol_objectid = key .offset ;
893
+
894
+ root_ref = btrfs_item_ptr (path -> nodes [0 ], path -> slots [0 ],
895
+ struct btrfs_root_ref );
896
+ len = btrfs_root_ref_name_len (path -> nodes [0 ], root_ref );
897
+ ptr -= len + 1 ;
898
+ if (ptr < name ) {
899
+ ret = - ENAMETOOLONG ;
900
+ goto err ;
901
+ }
902
+ read_extent_buffer (path -> nodes [0 ], ptr + 1 ,
903
+ (unsigned long )(root_ref + 1 ), len );
904
+ ptr [0 ] = '/' ;
905
+ dirid = btrfs_root_ref_dirid (path -> nodes [0 ], root_ref );
906
+ btrfs_release_path (path );
907
+
908
+ key .objectid = subvol_objectid ;
909
+ key .type = BTRFS_ROOT_ITEM_KEY ;
910
+ key .offset = (u64 )- 1 ;
911
+ fs_root = btrfs_read_fs_root_no_name (fs_info , & key );
912
+ if (IS_ERR (fs_root )) {
913
+ ret = PTR_ERR (fs_root );
914
+ goto err ;
915
+ }
916
+
917
+ /*
918
+ * Walk up the filesystem tree by inode refs until we hit the
919
+ * root directory.
920
+ */
921
+ while (dirid != BTRFS_FIRST_FREE_OBJECTID ) {
922
+ key .objectid = dirid ;
923
+ key .type = BTRFS_INODE_REF_KEY ;
924
+ key .offset = (u64 )- 1 ;
925
+
926
+ ret = btrfs_search_slot (NULL , fs_root , & key , path , 0 , 0 );
927
+ if (ret < 0 ) {
928
+ goto err ;
929
+ } else if (ret > 0 ) {
930
+ ret = btrfs_previous_item (fs_root , path , dirid ,
931
+ BTRFS_INODE_REF_KEY );
932
+ if (ret < 0 ) {
933
+ goto err ;
934
+ } else if (ret > 0 ) {
935
+ ret = - ENOENT ;
936
+ goto err ;
937
+ }
938
+ }
939
+
940
+ btrfs_item_key_to_cpu (path -> nodes [0 ], & key , path -> slots [0 ]);
941
+ dirid = key .offset ;
942
+
943
+ inode_ref = btrfs_item_ptr (path -> nodes [0 ],
944
+ path -> slots [0 ],
945
+ struct btrfs_inode_ref );
946
+ len = btrfs_inode_ref_name_len (path -> nodes [0 ],
947
+ inode_ref );
948
+ ptr -= len + 1 ;
949
+ if (ptr < name ) {
950
+ ret = - ENAMETOOLONG ;
951
+ goto err ;
952
+ }
953
+ read_extent_buffer (path -> nodes [0 ], ptr + 1 ,
954
+ (unsigned long )(inode_ref + 1 ), len );
955
+ ptr [0 ] = '/' ;
956
+ btrfs_release_path (path );
957
+ }
861
958
}
862
959
960
+ btrfs_free_path (path );
961
+ if (ptr == name + PATH_MAX - 1 ) {
962
+ name [0 ] = '/' ;
963
+ name [1 ] = '\0' ;
964
+ } else {
965
+ memmove (name , ptr , name + PATH_MAX - ptr );
966
+ }
967
+ return name ;
968
+
969
+ err :
970
+ btrfs_free_path (path );
971
+ kfree (name );
972
+ return ERR_PTR (ret );
973
+ }
974
+
975
+ static int get_default_subvol_objectid (struct btrfs_fs_info * fs_info , u64 * objectid )
976
+ {
977
+ struct btrfs_root * root = fs_info -> tree_root ;
978
+ struct btrfs_dir_item * di ;
979
+ struct btrfs_path * path ;
980
+ struct btrfs_key location ;
981
+ u64 dir_id ;
982
+
863
983
path = btrfs_alloc_path ();
864
984
if (!path )
865
- return ERR_PTR ( - ENOMEM ) ;
985
+ return - ENOMEM ;
866
986
path -> leave_spinning = 1 ;
867
987
868
988
/*
@@ -874,58 +994,23 @@ static struct dentry *get_default_root(struct super_block *sb,
874
994
di = btrfs_lookup_dir_item (NULL , root , path , dir_id , "default" , 7 , 0 );
875
995
if (IS_ERR (di )) {
876
996
btrfs_free_path (path );
877
- return ERR_CAST (di );
997
+ return PTR_ERR (di );
878
998
}
879
999
if (!di ) {
880
1000
/*
881
1001
* Ok the default dir item isn't there. This is weird since
882
1002
* it's always been there, but don't freak out, just try and
883
- * mount to root most subvolume.
1003
+ * mount the top-level subvolume.
884
1004
*/
885
1005
btrfs_free_path (path );
886
- dir_id = BTRFS_FIRST_FREE_OBJECTID ;
887
- new_root = fs_info -> fs_root ;
888
- goto setup_root ;
1006
+ * objectid = BTRFS_FS_TREE_OBJECTID ;
1007
+ return 0 ;
889
1008
}
890
1009
891
1010
btrfs_dir_item_key_to_cpu (path -> nodes [0 ], di , & location );
892
1011
btrfs_free_path (path );
893
-
894
- find_root :
895
- new_root = btrfs_read_fs_root_no_name (fs_info , & location );
896
- if (IS_ERR (new_root ))
897
- return ERR_CAST (new_root );
898
-
899
- if (!(sb -> s_flags & MS_RDONLY )) {
900
- int ret ;
901
- down_read (& fs_info -> cleanup_work_sem );
902
- ret = btrfs_orphan_cleanup (new_root );
903
- up_read (& fs_info -> cleanup_work_sem );
904
- if (ret )
905
- return ERR_PTR (ret );
906
- }
907
-
908
- dir_id = btrfs_root_dirid (& new_root -> root_item );
909
- setup_root :
910
- location .objectid = dir_id ;
911
- location .type = BTRFS_INODE_ITEM_KEY ;
912
- location .offset = 0 ;
913
-
914
- inode = btrfs_iget (sb , & location , new_root , & new );
915
- if (IS_ERR (inode ))
916
- return ERR_CAST (inode );
917
-
918
- /*
919
- * If we're just mounting the root most subvol put the inode and return
920
- * a reference to the dentry. We will have already gotten a reference
921
- * to the inode in btrfs_fill_super so we're good to go.
922
- */
923
- if (!new && d_inode (sb -> s_root ) == inode ) {
924
- iput (inode );
925
- return dget (sb -> s_root );
926
- }
927
-
928
- return d_obtain_root (inode );
1012
+ * objectid = location .objectid ;
1013
+ return 0 ;
929
1014
}
930
1015
931
1016
static int btrfs_fill_super (struct super_block * sb ,
@@ -1211,6 +1296,25 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
1211
1296
goto out ;
1212
1297
}
1213
1298
1299
+ if (!subvol_name ) {
1300
+ if (!subvol_objectid ) {
1301
+ ret = get_default_subvol_objectid (btrfs_sb (mnt -> mnt_sb ),
1302
+ & subvol_objectid );
1303
+ if (ret ) {
1304
+ root = ERR_PTR (ret );
1305
+ goto out ;
1306
+ }
1307
+ }
1308
+ subvol_name = get_subvol_name_from_objectid (btrfs_sb (mnt -> mnt_sb ),
1309
+ subvol_objectid );
1310
+ if (IS_ERR (subvol_name )) {
1311
+ root = ERR_CAST (subvol_name );
1312
+ subvol_name = NULL ;
1313
+ goto out ;
1314
+ }
1315
+
1316
+ }
1317
+
1214
1318
root = mount_subtree (mnt , subvol_name );
1215
1319
/* mount_subtree() drops our reference on the vfsmount. */
1216
1320
mnt = NULL ;
@@ -1227,6 +1331,11 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
1227
1331
ret = - EINVAL ;
1228
1332
}
1229
1333
if (subvol_objectid && root_objectid != subvol_objectid ) {
1334
+ /*
1335
+ * This will also catch a race condition where a
1336
+ * subvolume which was passed by ID is renamed and
1337
+ * another subvolume is renamed over the old location.
1338
+ */
1230
1339
pr_err ("BTRFS: subvol '%s' does not match subvolid %llu\n" ,
1231
1340
subvol_name , subvol_objectid );
1232
1341
ret = - EINVAL ;
@@ -1306,7 +1415,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
1306
1415
{
1307
1416
struct block_device * bdev = NULL ;
1308
1417
struct super_block * s ;
1309
- struct dentry * root ;
1310
1418
struct btrfs_fs_devices * fs_devices = NULL ;
1311
1419
struct btrfs_fs_info * fs_info = NULL ;
1312
1420
struct security_mnt_opts new_sec_opts ;
@@ -1326,7 +1434,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
1326
1434
return ERR_PTR (error );
1327
1435
}
1328
1436
1329
- if (subvol_name ) {
1437
+ if (subvol_name || subvol_objectid != BTRFS_FS_TREE_OBJECTID ) {
1330
1438
/* mount_subvol() will free subvol_name. */
1331
1439
return mount_subvol (subvol_name , subvol_objectid , flags ,
1332
1440
device_name , data );
@@ -1395,23 +1503,19 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
1395
1503
error = btrfs_fill_super (s , fs_devices , data ,
1396
1504
flags & MS_SILENT ? 1 : 0 );
1397
1505
}
1398
-
1399
- root = !error ? get_default_root (s , subvol_objectid ) : ERR_PTR (error );
1400
- if (IS_ERR (root )) {
1506
+ if (error ) {
1401
1507
deactivate_locked_super (s );
1402
- error = PTR_ERR (root );
1403
1508
goto error_sec_opts ;
1404
1509
}
1405
1510
1406
1511
fs_info = btrfs_sb (s );
1407
1512
error = setup_security_options (fs_info , s , & new_sec_opts );
1408
1513
if (error ) {
1409
- dput (root );
1410
1514
deactivate_locked_super (s );
1411
1515
goto error_sec_opts ;
1412
1516
}
1413
1517
1414
- return root ;
1518
+ return dget ( s -> s_root ) ;
1415
1519
1416
1520
error_close_devices :
1417
1521
btrfs_close_devices (fs_devices );
0 commit comments