@@ -1083,6 +1083,8 @@ int btrfs_mkfs_validate_subvols(const char *source_dir, struct list_head *subvol
10831083
10841084 list_for_each_entry (rds , subvols , list ) {
10851085 char path [PATH_MAX ];
1086+ char full_path [PATH_MAX ];
1087+ struct stat stbuf ;
10861088 struct rootdir_subvol * rds2 ;
10871089 int ret ;
10881090
@@ -1092,29 +1094,37 @@ int btrfs_mkfs_validate_subvols(const char *source_dir, struct list_head *subvol
10921094 error ("path invalid '%s': %m" , path );
10931095 return ret ;
10941096 }
1095- if (!realpath (path , rds -> full_path )) {
1097+ if (!realpath (path , full_path )) {
10961098 ret = - errno ;
10971099 error ("could not get canonical path of '%s': %m" , rds -> dir );
10981100 return ret ;
10991101 }
1100- ret = path_exists (rds -> full_path );
1102+ ret = path_exists (full_path );
11011103 if (ret < 0 ) {
11021104 error ("subvolume path does not exist: %s" , rds -> dir );
11031105 return ret ;
11041106 }
1105- ret = path_is_dir (rds -> full_path );
1107+ ret = path_is_dir (full_path );
11061108 if (ret < 0 ) {
11071109 error ("subvolume is not a directory: %s" , rds -> dir );
11081110 return ret ;
11091111 }
1112+ ret = lstat (full_path , & stbuf );
1113+ if (ret < 0 ) {
1114+ ret = - errno ;
1115+ error ("failed to get stat of '%s': %m" , full_path );
1116+ return ret ;
1117+ }
1118+ rds -> st_dev = stbuf .st_dev ;
1119+ rds -> st_ino = stbuf .st_ino ;
11101120 list_for_each_entry (rds2 , subvols , list ) {
11111121 /*
11121122 * Only compare entries before us, So we won't compare
11131123 * the same pair twice.
11141124 */
11151125 if (rds2 == rds )
11161126 break ;
1117- if (strcmp ( rds2 -> full_path , rds -> full_path ) == 0 ) {
1127+ if (rds2 -> st_dev == rds -> st_dev && rds2 -> st_ino == rds -> st_ino ) {
11181128 error ("subvolume specified more than once: %s" , rds -> dir );
11191129 return - EINVAL ;
11201130 }
@@ -1424,15 +1434,26 @@ static int ftw_add_subvol(const char *full_path, const struct stat *st,
14241434 struct btrfs_root * new_root ;
14251435 struct inode_entry * parent ;
14261436 struct btrfs_inode_item inode_item = { 0 };
1437+ char * path_dump ;
1438+ char * base_path ;
14271439 u64 subvol_id , ino ;
14281440
14291441 subvol_id = next_subvol_id ++ ;
1442+ path_dump = strdup (full_path );
1443+ if (!path_dump )
1444+ return - ENOMEM ;
1445+ base_path = path_basename (path_dump );
1446+ if (!base_path ) {
1447+ ret = - errno ;
1448+ error ("failed to get basename of '%s': %m" , path_dump );
1449+ goto out ;
1450+ }
14301451
14311452 ret = btrfs_make_subvolume (g_trans , subvol_id , subvol -> readonly );
14321453 if (ret < 0 ) {
14331454 errno = - ret ;
14341455 error ("failed to create subvolume: %m" );
1435- return ret ;
1456+ goto out ;
14361457 }
14371458
14381459 if (subvol -> is_default )
@@ -1447,19 +1468,18 @@ static int ftw_add_subvol(const char *full_path, const struct stat *st,
14471468 ret = PTR_ERR (new_root );
14481469 errno = - ret ;
14491470 error ("unable to read fs root id %llu: %m" , subvol_id );
1450- return ret ;
1471+ goto out ;
14511472 }
14521473
14531474 parent = rootdir_path_last (& current_path );
14541475
14551476 ret = btrfs_link_subvolume (g_trans , parent -> root , parent -> ino ,
1456- path_basename (subvol -> full_path ),
1457- strlen (path_basename (subvol -> full_path )),
1477+ base_path , strlen (base_path ),
14581478 new_root );
14591479 if (ret ) {
14601480 errno = - ret ;
1461- error ("unable to link subvolume %s: %m" , path_basename ( subvol -> full_path ) );
1462- return ret ;
1481+ error ("unable to link subvolume %s: %m" , base_path );
1482+ goto out ;
14631483 }
14641484
14651485 ino = btrfs_root_dirid (& new_root -> root_item );
@@ -1469,7 +1489,7 @@ static int ftw_add_subvol(const char *full_path, const struct stat *st,
14691489 errno = - ret ;
14701490 error ("failed to add xattr item for the top level inode in subvol %llu: %m" ,
14711491 subvol_id );
1472- return ret ;
1492+ goto out ;
14731493 }
14741494 stat_to_inode_item (& inode_item , st );
14751495
@@ -1479,18 +1499,20 @@ static int ftw_add_subvol(const char *full_path, const struct stat *st,
14791499 if (ret < 0 ) {
14801500 errno = - ret ;
14811501 error ("failed to update root dir for root %llu: %m" , subvol_id );
1482- return ret ;
1502+ goto out ;
14831503 }
14841504
14851505 ret = rootdir_path_push (& current_path , new_root , ino );
14861506 if (ret < 0 ) {
14871507 errno = - ret ;
14881508 error ("failed to allocate new entry for subvolume %llu ('%s'): %m" ,
14891509 subvol_id , full_path );
1490- return ret ;
1510+ goto out ;
14911511 }
14921512
1493- return 0 ;
1513+ out :
1514+ free (path_dump );
1515+ return ret ;
14941516}
14951517
14961518static int read_inode_item (struct btrfs_root * root , struct btrfs_inode_item * inode_item ,
@@ -1611,7 +1633,7 @@ static int ftw_add_inode(const char *full_path, const struct stat *st,
16111633
16121634 if (S_ISDIR (st -> st_mode )) {
16131635 list_for_each_entry (rds , g_subvols , list ) {
1614- if (! strcmp ( full_path , rds -> full_path ) ) {
1636+ if (st -> st_dev == rds -> st_dev && st -> st_ino == rds -> st_ino ) {
16151637 ret = ftw_add_subvol (full_path , st , typeflag ,
16161638 ftwbuf , rds );
16171639
0 commit comments