2929
3030struct cache_dfs_tgt {
3131 char * name ;
32+ int path_consumed ;
3233 struct list_head list ;
3334};
3435
@@ -350,7 +351,7 @@ static inline struct timespec64 get_expire_time(int ttl)
350351}
351352
352353/* Allocate a new DFS target */
353- static struct cache_dfs_tgt * alloc_target (const char * name )
354+ static struct cache_dfs_tgt * alloc_target (const char * name , int path_consumed )
354355{
355356 struct cache_dfs_tgt * t ;
356357
@@ -362,6 +363,7 @@ static struct cache_dfs_tgt *alloc_target(const char *name)
362363 kfree (t );
363364 return ERR_PTR (- ENOMEM );
364365 }
366+ t -> path_consumed = path_consumed ;
365367 INIT_LIST_HEAD (& t -> list );
366368 return t ;
367369}
@@ -384,7 +386,7 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
384386 for (i = 0 ; i < numrefs ; i ++ ) {
385387 struct cache_dfs_tgt * t ;
386388
387- t = alloc_target (refs [i ].node_name );
389+ t = alloc_target (refs [i ].node_name , refs [ i ]. path_consumed );
388390 if (IS_ERR (t )) {
389391 free_tgts (ce );
390392 return PTR_ERR (t );
@@ -830,6 +832,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
830832 rc = - ENOMEM ;
831833 goto err_free_it ;
832834 }
835+ it -> it_path_consumed = t -> path_consumed ;
833836
834837 if (ce -> tgthint == t )
835838 list_add (& it -> it_list , head );
@@ -1320,23 +1323,26 @@ void dfs_cache_del_vol(const char *fullpath)
13201323/**
13211324 * dfs_cache_get_tgt_share - parse a DFS target
13221325 *
1326+ * @path: DFS full path
13231327 * @it: DFS target iterator.
13241328 * @share: tree name.
1325- * @share_len: length of tree name.
13261329 * @prefix: prefix path.
1327- * @prefix_len: length of prefix path.
13281330 *
13291331 * Return zero if target was parsed correctly, otherwise non-zero.
13301332 */
1331- int dfs_cache_get_tgt_share (const struct dfs_cache_tgt_iterator * it ,
1332- const char * * share , size_t * share_len ,
1333- const char * * prefix , size_t * prefix_len )
1333+ int dfs_cache_get_tgt_share (char * path , const struct dfs_cache_tgt_iterator * it ,
1334+ char * * share , char * * prefix )
13341335{
1335- char * s , sep ;
1336+ char * s , sep , * p ;
1337+ size_t len ;
1338+ size_t plen1 , plen2 ;
13361339
1337- if (!it || !share || !share_len || !prefix || ! prefix_len )
1340+ if (!it || !path || !share || !prefix || strlen ( path ) < it -> it_path_consumed )
13381341 return - EINVAL ;
13391342
1343+ * share = NULL ;
1344+ * prefix = NULL ;
1345+
13401346 sep = it -> it_name [0 ];
13411347 if (sep != '\\' && sep != '/' )
13421348 return - EINVAL ;
@@ -1345,13 +1351,38 @@ int dfs_cache_get_tgt_share(const struct dfs_cache_tgt_iterator *it,
13451351 if (!s )
13461352 return - EINVAL ;
13471353
1354+ /* point to prefix in target node */
13481355 s = strchrnul (s + 1 , sep );
13491356
1350- * share = it -> it_name ;
1351- * share_len = s - it -> it_name ;
1352- * prefix = * s ? s + 1 : s ;
1353- * prefix_len = & it -> it_name [ strlen ( it -> it_name )] - * prefix ;
1357+ /* extract target share */
1358+ * share = kstrndup ( it -> it_name , s - it -> it_name , GFP_KERNEL ) ;
1359+ if (! * share )
1360+ return - ENOMEM ;
13541361
1362+ /* skip separator */
1363+ if (* s )
1364+ s ++ ;
1365+ /* point to prefix in DFS path */
1366+ p = path + it -> it_path_consumed ;
1367+ if (* p == sep )
1368+ p ++ ;
1369+
1370+ /* merge prefix paths from DFS path and target node */
1371+ plen1 = it -> it_name + strlen (it -> it_name ) - s ;
1372+ plen2 = path + strlen (path ) - p ;
1373+ if (plen1 || plen2 ) {
1374+ len = plen1 + plen2 + 2 ;
1375+ * prefix = kmalloc (len , GFP_KERNEL );
1376+ if (!* prefix ) {
1377+ kfree (* share );
1378+ * share = NULL ;
1379+ return - ENOMEM ;
1380+ }
1381+ if (plen1 )
1382+ scnprintf (* prefix , len , "%.*s%c%.*s" , (int )plen1 , s , sep , (int )plen2 , p );
1383+ else
1384+ strscpy (* prefix , p , len );
1385+ }
13551386 return 0 ;
13561387}
13571388
0 commit comments