summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2026-01-30NFS: Add a way to disable NFS v4.0 via KConfigAnna Schumaker8-5/+47
I introduce NFS4_MIN_MINOR_VERSION as a parallel to NFS4_MAX_MINOR_VERSION to check if NFS v4.0 has been compiled in and return an appropriate error if not. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Move sequence slot operations into minorversion operationsAnna Schumaker4-72/+70
At the same time, I move the NFS v4.0 functions into nfs40proc.c to keep v4.0 features together in their own files. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Pass a struct nfs_client to nfs4_init_sequence()Anna Schumaker4-69/+87
No functional change in this patch. This just makes the next patch where I introduce "sequence slot operations" simpler. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Move NFS v4.0 pathdown recovery into nfs40client.cAnna Schumaker3-22/+25
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Move nfs40_init_client into nfs40client.cAnna Schumaker4-28/+28
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Move nfs40_shutdown_client into nfs40client.cAnna Schumaker5-9/+13
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Make the various NFS v4.0 operations static againAnna Schumaker2-10/+5
They don't need to be visible outside of nfs40proc.c anymore now that the minor version ops have been moved over. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Move the NFS v4.0 minor version ops into nfs40proc.cAnna Schumaker4-111/+115
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Split out the nfs40_mig_recovery_ops to nfs40proc.cAnna Schumaker4-109/+114
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Split out the nfs40_state_renewal_ops into nfs40proc.cAnna Schumaker4-101/+103
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Split out the nfs40_nograce_recovery_ops into nfs40proc.cAnna Schumaker4-29/+34
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Split out the nfs40_reboot_recovery_ops into nfs40client.cAnna Schumaker9-194/+214
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-30NFS: Move nfs40_call_sync_ops into nfs40proc.cAnna Schumaker5-25/+40
This is the first step in extracting NFS v4.0 into its own set of files that can be disabled through Kconfig. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-22NFS/localio: switch nfs_local_do_read and nfs_local_do_write to return voidMike Snitzer1-19/+13
Both nfs_local_do_read and nfs_local_do_write only return 0 at the end, so switch them to returning void. Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-22NFS/localio: remove -EAGAIN handling in nfs_local_doio()Mike Snitzer1-2/+0
Handling -EAGAIN in nfs_local_doio() was introduced with commit 0978e5b85fc08 (nfs_do_local_{read,write} were made to have negative checks for correspoding iter method) but commit e43e9a3a3d66 since eliminated the possibility for this -EAGAIN early return. So remove nfs_local_doio()'s -EAGAIN handling that calls nfs_localio_disable_client() -- while it should never happen from nfs_do_local_{read,write} this particular -EAGAIN handling is now "dead" and so it has become a liability. Fixes: e43e9a3a3d66 ("nfs/localio: refactor iocb initialization") Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-22NFS/localio: use GFP_NOIO and non-memreclaim workqueue in nfs_local_commitMike Snitzer1-3/+8
nfslocaliod_workqueue is a non-memreclaim workqueue (it isn't initialized with WQ_MEM_RECLAIM), see commit b9f5dd57f4a5 ("nfs/localio: use dedicated workqueues for filesystem read and write"). Use nfslocaliod_workqueue for LOCALIO's SYNC work. Also, set PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO in nfs_local_fsync_work. Fixes: b9f5dd57f4a5 ("nfs/localio: use dedicated workqueues for filesystem read and write") Signed-off-by: Mike Snitzer <snitzer@hammerspace.com> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-22NFS/localio: prevent direct reclaim recursion into NFS via nfs_writepagesMike Snitzer1-0/+15
LOCALIO is an NFS loopback mount optimization that avoids using the network for READ, WRITE and COMMIT if the NFS client and server are determined to be on the same system. But because LOCALIO is still fundamentally "just NFS loopback mount" it is susceptible to recursion deadlock via direct reclaim, e.g.: NFS LOCALIO down to XFS and then back into NFS via nfs_writepages. Fix LOCALIO's potential for direct reclaim deadlock by ensuring that all its page cache allocations are done from GFP_NOFS context. Thanks to Ben Coddington for pointing out commit ad22c7a043c2 ("xfs: prevent stack overflows from page cache allocation"). Reported-by: John Cagle <john.cagle@hammerspace.com> Tested-by: Allen Lu <allen.lu@hammerspace.com> Suggested-by: Benjamin Coddington <bcodding@hammerspace.com> Fixes: 70ba381e1a43 ("nfs: add LOCALIO support") Signed-off-by: Mike Snitzer <snitzer@hammerspace.com> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-22NFS/localio: Cleanup the nfs_local_pgio_done() parametersTrond Myklebust1-9/+5
Remove the redundant 'force' parameter. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-22NFS/localio: Handle short writes by retryingTrond Myklebust1-17/+47
The current code for handling short writes in localio just truncates the I/O and then sets an error. While that is close to how the ordinary NFS code behaves, it does mean there is a chance the data that got written is lost because it isn't persisted. To fix this, change localio so that the upper layers can direct the behaviour to persist any unstable data by rewriting it, and then continuing writing until an ENOSPC is hit. Fixes: 70ba381e1a43 ("nfs: add LOCALIO support") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Reviewed-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: make nfs_mark_return_unreferenced_delegations less aggressiveChristoph Hellwig1-7/+17
Currently nfs_mark_return_unreferenced_delegations marks all open but not referenced delegations (i.e., those were found by a previous pass) as return on close, which means that we'll return them on close without a way out. Replace this with only iterating delegations that are on the LRU list, and avoid delegations that are in use by an open files to avoid this. Delegations that were never referenced while open still are be prime candidates for return from the LRU if the number of delegations is over the watermark, or otherwise will be returned by the next nfs_mark_return_unreferenced_delegations pass after they are closed. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: return delegations from the end of a LRU when over the watermarkChristoph Hellwig3-3/+60
Directly returning delegations on close when over the watermark is rather suboptimal as these delegations are much more likely to be reused than those that have been unused for a long time. Switch to returning unused delegations from a new LRU list when we are above the threshold and there are reclaimable delegations instead. Pass over referenced delegations during the first pass to give delegations that aren't in active used by frequently used for stat() or similar another chance to not be instantly reclaimed. This scheme works the same as the referenced flags in the VFS inode and dentry caches. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: add a separate delegation return listChristoph Hellwig5-87/+85
Searching for returnable delegations in the per-server delegations list can be very expensive. While commit e04bbf6b1bbe ("NFS: Avoid quadratic search when freeing delegations.") reduced the overhead a bit, the fact that all the non-returnable delegations have to be searched limits the amount of optimizations that can be done. Fix this by introducing a separate list that only contains delegations scheduled for return. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: reformat nfs_mark_delegation_revokedChristoph Hellwig1-6/+7
Remove a level of indentation for the main code path. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: use a local RCU critical section in nfs_start_delegation_returnChristoph Hellwig1-6/+5
Nested RCU critical sections are fine and very cheap. Have a local one in nfs_start_delegation_return so that the function is self-contained and to prepare for simplifying the callers. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: use refcount_inc_not_zero nfs_start_delegation_returnChristoph Hellwig1-12/+10
Using the unconditional reference increment means we can take a reference to a delegation already in the RCU grace period, which could cause a use after free under very unlikely conditions. Switch to use refcount_inc_not_zero instead. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: don't consume a delegation reference in nfs_end_delegation_returnChristoph Hellwig1-22/+24
All callers now hold references to the delegation as part of the lookup, removing the need for an extra reference for those that are actually returned which is then dropped in nfs_end_delegation_return. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: take a delegation reference in nfs4_get_valid_delegationChristoph Hellwig4-46/+56
Currently most work on struct nfs_delegation happens directly under RCU protection. This is generally fine, despite that long RCU sections are not good for performance. But for operations later taking a reference to the delegation to perform blocking work, refcount_inc is used, which can be racy against dropping the last reference and thus lead to use after frees in extremely rare cases. Fix this by taking a reference in nfs4_get_valid_delegation using refcount_inc_not_zero so that the callers have a stabilized reference they can work with and can be moved outside the RCU critical section. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: simplify the detached delegation check in update_open_stateidChristoph Hellwig1-2/+1
When nfs_detach_delegation_locked detaches a delegation from an inode, it clears both nfsi->delegation and delegation->inode. Use the later in update_open_stateid to check for a detached inode, as that avoids an extra local variable, and removes the need for a RCU derefernence as we already hold the lock in the delegation. This prepares for removing the surrounding RCU critical section. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: move the deleg_cur check out of nfs_detach_delegation_lockedChristoph Hellwig1-8/+7
nfs_inode_set_delegation as the only direct caller of nfs_detach_delegation_locked already check this under cl_lock, so don't repeat it. Replace the lockdep coverage for the lock that was implicitly provided by the rcu_dereference_protected call that is removed with an explicit lockdep assert to keep the coverage. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: return bool from nfs_detach_delegation{,_locked}Christoph Hellwig1-13/+14
nfs_detach_delegation always returns either the passed in delegation or NULL, simplify this to a bool return. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: move delegation lookup into can_open_delegatedChristoph Hellwig1-32/+33
Keep the delegation handling in a single place, and just return the stateid in an optional argument. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: rewrite nfs_delegations_present in terms of nr_active_delegationsChristoph Hellwig1-1/+1
Renewal only cares for active delegations and not revoked ones. Replace the list empty check with reading the active delegation counter to implement this. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove nfs_free_delegationChristoph Hellwig1-11/+8
Open code nfs_free_delegation in the callers, because having a "free" function that wraps a revoke and put operation is a bit confusing, especially when the __free version does the actual freeing triggered by the last put. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: open code nfs_delegation_need_returnChristoph Hellwig1-17/+7
There is only a single caller, and the function can be condensed into a single if statement, making it more clear what is being tested there. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove NFS_DELEGATION_INODE_FREEINGChristoph Hellwig3-13/+2
This essentially reverts commit 6f9449be53f3 ("NFS: Fix a soft lockup in the delegation recovery code") because the code walking the per-server delegation list has been fixed to just skip inodes for which nfs_delegation_grab_inode fails, instead of having to restart the entire series in commit f92214e4c312 ("NFS: Avoid unnecessary rescanning of the per-server delegation list"). Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: drop the _locked postfix from nfs_start_delegation_returnChristoph Hellwig1-6/+6
Now that nfs_start_delegation_return_locked is gone, and we have RCU locking asserts, drop the extra postfix. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: assert rcu_read_lock is held in nfs_start_delegation_return_lockedChristoph Hellwig1-4/+7
And clean up the dereference of the delegation a bit. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove nfs_start_delegation_returnChristoph Hellwig1-20/+12
There is only one caller, so fold it into that. With that, nfs_start_delegation_return Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove nfs_inode_detach_delegationChristoph Hellwig1-22/+15
Fold it into the only caller. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove the NULL inode check in nfs4_inode_return_delegation_on_closeChristoph Hellwig1-2/+0
The only caller dereferences a field in the inode just before calling nfs4_inode_return_delegation_on_close. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove nfs_client_mark_return_all_delegationsChristoph Hellwig1-11/+7
Fold nfs_client_mark_return_all_delegations into nfs_expire_all_delegations, which is the only caller. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove nfs_client_mark_return_unused_delegation_typesChristoph Hellwig1-14/+3
nfs_client_mark_return_unused_delegation_types is only called by nfs_expire_unused_delegation_types, so merge the two. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-20NFS: remove __nfs_client_for_each_serverChristoph Hellwig1-11/+3
__nfs_client_for_each_server is only called by nfs_client_for_each_server, so merge the two. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2026-01-19Linux 6.19-rc6v6.19-rc6Linus Torvalds1-1/+1
2026-01-19Merge tag 'landlock-6.19-rc6' of ↵Linus Torvalds14-269/+170
git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux Pull landlock fixes from Mickaël Salaün: "This fixes TCP handling, tests, documentation, non-audit elided code, and minor cosmetic changes" * tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: landlock: Clarify documentation for the IOCTL access right selftests/landlock: Properly close a file descriptor landlock: Improve the comment for domain_is_scoped selftests/landlock: Use scoped_base_variants.h for ptrace_test selftests/landlock: Fix missing semicolon selftests/landlock: Fix typo in fs_test landlock: Optimize stack usage when !CONFIG_AUDIT landlock: Fix spelling landlock: Clean up hook_ptrace_access_check() landlock: Improve erratum documentation landlock: Remove useless include landlock: Fix wrong type usage selftests/landlock: NULL-terminate unix pathname addresses selftests/landlock: Remove invalid unix socket bind() selftests/landlock: Add missing connect(minimal AF_UNSPEC) test selftests/landlock: Fix TCP bind(AF_UNSPEC) test case landlock: Fix TCP handling of short AF_UNSPEC addresses landlock: Fix formatting
2026-01-19Merge tag 'cgroup-for-6.19-rc5-fixes-2' of ↵Linus Torvalds4-16/+4
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup Pull cgroup fixes from Tejun Heo: - Add Chen Ridong as cpuset reviewer - Add SPDX license identifiers to cgroup files that were missing them * tag 'cgroup-for-6.19-rc5-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: kernel: cgroup: Add LGPL-2.1 SPDX license ID to legacy_freezer.c kernel: cgroup: Add SPDX-License-Identifier lines MAINTAINERS: Add Chen Ridong as cpuset reviewer
2026-01-19Merge tag 'ext4_for_linus-6.19-rc6' of ↵Linus Torvalds3-1/+4
git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 fixes from Ted Ts'o: - Fix an inconsistency in structure size on 32-bit platforms caused by padding differences for the new EXT4_IOC_[GS]ET_TUNE_SB_PARAM ioctls - Fix a buffer leak on the error path when dropping the refcount an xattr value stored in an inode - Fix missing locking on the error path for the file defragmentation ioctl leading to a BUG * tag 'ext4_for_linus-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: fix iloc.bh leak in ext4_xattr_inode_update_ref ext4: add missing down_write_data_sem in mext_move_extent(). ext4: fix ext4_tune_sb_params padding
2026-01-19Merge tag 'dmaengine-fix-6.19' of ↵Linus Torvalds20-73/+168
git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine Pull dmaengine fixes from Vinod Koul: "A bunch of driver fixes for: - dma mask fix for mmp pdma driver - Xilinx regmap max register, uninitialized addr_width fix - device leak fix for bunch of drivers in the subsystem - stm32 dmamux, TI crossbar driver fixes for device & of node leak and route allocation cleanup - Tegra use afer free fix - Memory leak fix in Qualcomm gpi and omap-dma driver - compatible fix for apple driver" * tag 'dmaengine-fix-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (25 commits) dmaengine: apple-admac: Add "apple,t8103-admac" compatible dmaengine: omap-dma: fix dma_pool resource leak in error paths dmaengine: qcom: gpi: Fix memory leak in gpi_peripheral_config() dmaengine: sh: rz-dmac: Fix rz_dmac_terminate_all() dmaengine: xilinx_dma: Fix uninitialized addr_width when "xlnx,addrwidth" property is missing dmaengine: tegra-adma: Fix use-after-free dmaengine: fsl-edma: Fix clk leak on alloc_chan_resources failure dmaengine: mmp_pdma: Fix race condition in mmp_pdma_residue() dmaengine: ti: k3-udma: fix device leak on udma lookup dmaengine: ti: dma-crossbar: clean up dra7x route allocation error paths dmaengine: ti: dma-crossbar: fix device leak on am335x route allocation dmaengine: ti: dma-crossbar: fix device leak on dra7x route allocation dmaengine: stm32: dmamux: clean up route allocation error labels dmaengine: stm32: dmamux: fix OF node leak on route allocation failure dmaengine: stm32: dmamux: fix device leak on route allocation dmaengine: sh: rz-dmac: fix device leak on probe failure dmaengine: lpc32xx-dmamux: fix device leak on route allocation dmaengine: lpc18xx-dmamux: fix device leak on route allocation dmaengine: idxd: fix device leaks on compat bind and unbind dmaengine: dw: dmamux: fix OF node leak on route allocation failure ...
2026-01-19Merge tag 'phy-fixes-6.19' of ↵Linus Torvalds11-50/+33
git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy Pull phy fixes from Vinod Koul: "A bunch of driver fixes: - Freescale typec orientation switch fix, clearing register fix, assertion of phy reset during power on - Qualcomm pcs register clear before using - stm one off fix - TI runtimepm error handling, regmap leak fixes - Rockchip gadget mode disconnection and disruption fixes - Tegra register level fix - Broadcom pointer cast warning fix" * tag 'phy-fixes-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: phy: freescale: imx8m-pcie: assert phy reset during power on phy: rockchip: inno-usb2: Fix a double free bug in rockchip_usb2phy_probe() phy: broadcom: ns-usb3: Fix Wvoid-pointer-to-enum-cast warning (again) phy: tegra: xusb: Explicitly configure HS_DISCON_LEVEL to 0x7 phy: rockchip: inno-usb2: fix communication disruption in gadget mode phy: rockchip: inno-usb2: fix disconnection in gadget mode phy: ti: gmii-sel: fix regmap leak on probe failure phy: sparx5-serdes: make it selectable for ARCH_LAN969X phy: ti: da8xx-usb: Handle devm_pm_runtime_enable() errors phy: stm32-usphyc: Fix off by one in probe() phy: qcom-qusb2: Fix NULL pointer dereference on early suspend phy: fsl-imx8mq-usb: Clear the PCS_TX_SWING_FULL field before using it dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Update pcie phy bindings for qcs8300 phy: fsl-imx8mq-usb: fix typec orientation switch when built as module
2026-01-18Merge tag 'soundwire-6.19-fixes' of ↵Linus Torvalds1-1/+1
git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire Pull soundwire fix from Vinod Koul: - Single off-by-one fix for allocating slave id * tag 'soundwire-6.19-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: soundwire: bus: fix off-by-one when allocating slave IDs