@@ -1580,38 +1580,42 @@ static inline int may_lookup(struct nameidata *nd)
1580
1580
return inode_permission (nd -> inode , MAY_EXEC );
1581
1581
}
1582
1582
1583
+ static int reserve_stack (struct nameidata * nd , struct path * link , unsigned seq )
1584
+ {
1585
+ int error ;
1586
+
1587
+ if (unlikely (nd -> total_link_count ++ >= MAXSYMLINKS ))
1588
+ return - ELOOP ;
1589
+ error = nd_alloc_stack (nd );
1590
+ if (likely (!error ))
1591
+ return 0 ;
1592
+ if (error == - ECHILD ) {
1593
+ // we must grab link first
1594
+ bool grabbed_link = legitimize_path (nd , link , seq );
1595
+ // ... and we must unlazy to be able to clean up
1596
+ error = unlazy_walk (nd );
1597
+ if (unlikely (!grabbed_link ))
1598
+ error = - ECHILD ;
1599
+ if (!error )
1600
+ error = nd_alloc_stack (nd );
1601
+ }
1602
+ return error ;
1603
+ }
1604
+
1583
1605
enum {WALK_TRAILING = 1 , WALK_MORE = 2 , WALK_NOFOLLOW = 4 };
1584
1606
1585
1607
static const char * pick_link (struct nameidata * nd , struct path * link ,
1586
1608
struct inode * inode , unsigned seq , int flags )
1587
1609
{
1588
1610
struct saved * last ;
1589
1611
const char * res ;
1590
- int error ;
1612
+ int error = reserve_stack ( nd , link , seq ) ;
1591
1613
1592
- if (unlikely (nd -> total_link_count ++ >= MAXSYMLINKS )) {
1593
- if (!(nd -> flags & LOOKUP_RCU ))
1594
- path_put (link );
1595
- return ERR_PTR (- ELOOP );
1596
- }
1597
- error = nd_alloc_stack (nd );
1598
1614
if (unlikely (error )) {
1599
- if (error == - ECHILD ) {
1600
- // we must grab link first
1601
- bool grabbed_link = legitimize_path (nd , link , seq );
1602
- // ... and we must unlazy to be able to clean up
1603
- error = unlazy_walk (nd );
1604
- if (unlikely (!grabbed_link ))
1605
- error = - ECHILD ;
1606
- if (!error )
1607
- error = nd_alloc_stack (nd );
1608
- }
1609
- if (error ) {
1615
+ if (!(nd -> flags & LOOKUP_RCU ))
1610
1616
path_put (link );
1611
- return ERR_PTR (error );
1612
- }
1617
+ return ERR_PTR (error );
1613
1618
}
1614
-
1615
1619
last = nd -> stack + nd -> depth ++ ;
1616
1620
last -> link = * link ;
1617
1621
clear_delayed_call (& last -> done );
0 commit comments