From: Dan Carpenter <dan.carpenter@linaro.org>
To: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
Cc: linux-nfs@vger.kernel.org
Subject: [bug report] pNFS/flexfiles: don't attempt pnfs on fatal DS errors
Date: Thu, 28 Aug 2025 14:08:13 +0300 [thread overview]
Message-ID: <aLA4nePqG4rAUXMU@stanley.mountain> (raw)
Hello Tigran Mkrtchyan,
Commit f06bedfa62d5 ("pNFS/flexfiles: don't attempt pnfs on fatal DS
errors") from Jun 27, 2025 (linux-next), leads to the following
Smatch static checker warning:
fs/nfs/flexfilelayout/flexfilelayout.c:880 ff_layout_pg_init_read()
error: uninitialized symbol 'ds_idx'.
We recently changed ff_layout_choose_ds_for_read() from returning NULL to
returning error pointers. There are two bugs. One error path in
ff_layout_choose_ds_for_read() accidentally returns success. And some
of the callers are still checking for NULL instead of error pointers.
Btw, I'm always promoting my blog about error pointers and NULL:
https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/
It's not really related here, since we should not mix error pointers
and NULL but I still link to it because that's what they taught me in
my Trump Wealth Institute course on Search Engine Optimization.
Here is what ff_layout_choose_ds_for_read() looks like:
fs/nfs/flexfilelayout/flexfilelayout.c
758 static struct nfs4_pnfs_ds *
759 ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg,
760 u32 start_idx, u32 *best_idx,
761 bool check_device)
762 {
763 struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
764 struct nfs4_ff_layout_mirror *mirror;
765 struct nfs4_pnfs_ds *ds = ERR_PTR(-EAGAIN);
766 u32 idx;
767
768 /* mirrors are initially sorted by efficiency */
769 for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) {
770 mirror = FF_LAYOUT_COMP(lseg, idx);
771 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false);
772 if (IS_ERR(ds))
773 continue;
774
775 if (check_device &&
776 nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node))
777 continue;
Bug #1: If we hit this continue on the last iteration through the loop
then we return success and *best_idx is not initialized. It should be:
if (check_device &&
nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node)) {
ds = ERR_PTR(-EINVAL);
continue;
}
778
779 *best_idx = idx;
780 break;
781 }
782
783 return ds;
784 }
Bug #2: The whole rest of the call tree expects NULL and not error pointers.
For example, ff_layout_get_ds_for_read():
fs/nfs/flexfilelayout/flexfilelayout.c
812 static struct nfs4_pnfs_ds *
813 ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio,
814 u32 *best_idx)
815 {
816 struct pnfs_layout_segment *lseg = pgio->pg_lseg;
817 struct nfs4_pnfs_ds *ds;
818
819 ds = ff_layout_choose_best_ds_for_read(lseg, pgio->pg_mirror_idx,
820 best_idx);
821 if (ds || !pgio->pg_mirror_idx)
^^
822 return ds;
This needs to check for error pointers. But also if pgio->pg_mirror_idx
is zero, is that a success return? I don't know...
823 return ff_layout_choose_best_ds_for_read(lseg, 0, best_idx);
824 }
fs/nfs/flexfilelayout/flexfilelayout.c
842 static void
843 ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
844 struct nfs_page *req)
845 {
846 struct nfs_pgio_mirror *pgm;
847 struct nfs4_ff_layout_mirror *mirror;
848 struct nfs4_pnfs_ds *ds;
849 u32 ds_idx;
850
851 if (NFS_SERVER(pgio->pg_inode)->flags &
852 (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
853 pgio->pg_maxretrans = io_maxretrans;
854 retry:
855 pnfs_generic_pg_check_layout(pgio, req);
856 /* Use full layout for now */
857 if (!pgio->pg_lseg) {
858 ff_layout_pg_get_read(pgio, req, false);
859 if (!pgio->pg_lseg)
860 goto out_nolseg;
861 }
862 if (ff_layout_avoid_read_on_rw(pgio->pg_lseg)) {
863 ff_layout_pg_get_read(pgio, req, true);
864 if (!pgio->pg_lseg)
865 goto out_nolseg;
866 }
867 /* Reset wb_nio, since getting layout segment was successful */
868 req->wb_nio = 0;
869
870 ds = ff_layout_get_ds_for_read(pgio, &ds_idx);
871 if (!ds) {
^^^^^^^^^^
This doesn't check for error pointers either.
872 if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
873 goto out_mds;
874 pnfs_generic_pg_cleanup(pgio);
875 /* Sleep for 1 second before retrying */
876 ssleep(1);
877 goto retry;
878 }
879
--> 880 mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx);
^^^^^^
Uninitialized.
regards,
dan carpenter
next reply other threads:[~2025-08-28 11:08 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-28 11:08 Dan Carpenter [this message]
2025-08-28 11:18 ` [bug report] pNFS/flexfiles: don't attempt pnfs on fatal DS errors Mkrtchyan, Tigran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aLA4nePqG4rAUXMU@stanley.mountain \
--to=dan.carpenter@linaro.org \
--cc=linux-nfs@vger.kernel.org \
--cc=tigran.mkrtchyan@desy.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox