[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] vpci: introduce per-domain lock to protect vpci structure
On 14.02.22 16:19, Jan Beulich wrote: > On 09.02.2022 14:36, Oleksandr Andrushchenko wrote: >> @@ -410,14 +428,37 @@ static void vpci_write_helper(const struct pci_dev >> *pdev, >> r->private); >> } >> >> +static bool vpci_header_write_lock(const struct pci_dev *pdev, >> + unsigned int start, unsigned int size) >> +{ >> + /* >> + * Writing the command register and ROM BAR register may trigger >> + * modify_bars to run which in turn may access multiple pdevs while >> + * checking for the existing BAR's overlap. The overlapping check, if >> done >> + * under the read lock, requires vpci->lock to be acquired on both >> devices >> + * being compared, which may produce a deadlock. It is not possible to >> + * upgrade read lock to write lock in such a case. So, in order to >> prevent >> + * the deadlock, check which registers are going to be written and >> acquire >> + * the lock in the appropriate mode from the beginning. >> + */ >> + if ( !vpci_offset_cmp(start, size, PCI_COMMAND, 2) ) >> + return true; >> + >> + if ( !vpci_offset_cmp(start, size, pdev->vpci->header.rom_reg, 4) ) >> + return true; >> + >> + return false; >> +} > A function of this name gives (especially at the call site(s)) the > impression of acquiring a lock. Considering that of the prefixes > neither "vpci" nor "header" are really relevant here, may I suggest > to use need_write_lock()? > > May I further suggest that you either split the comment or combine > the two if()-s (perhaps even straight into single return statement)? > Personally I'd prefer the single return statement approach here ... That was already questioned by Roger and now it looks like: static bool overlap(unsigned int r1_offset, unsigned int r1_size, unsigned int r2_offset, unsigned int r2_size) { /* Return true if there is an overlap. */ return r1_offset < r2_offset + r2_size && r2_offset < r1_offset + r1_size; } bool vpci_header_write_lock(const struct pci_dev *pdev, unsigned int start, unsigned int size) { /* * Writing the command register and ROM BAR register may trigger * modify_bars to run which in turn may access multiple pdevs while * checking for the existing BAR's overlap. The overlapping check, if done * under the read lock, requires vpci->lock to be acquired on both devices * being compared, which may produce a deadlock. It is not possible to * upgrade read lock to write lock in such a case. So, in order to prevent * the deadlock, check which registers are going to be written and acquire * the lock in the appropriate mode from the beginning. */ if ( overlap(start, size, PCI_COMMAND, 2) || (pdev->vpci->header.rom_reg && overlap(start, size, pdev->vpci->header.rom_reg, 4)) ) return true; return false; } vpci_header_write_lock moved to header.c and is not static anymore. So, sitting in header.c, the name seems to be appropriate now > > Jan > Thank you, Oleksandr
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |