]> git.baikalelectronics.ru Git - kernel.git/commitdiff
NFSv4/flexfiles: Fix invalid deref in FF_LAYOUT_DEVID_NODE()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Tue, 26 Feb 2019 16:19:46 +0000 (11:19 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 1 Mar 2019 21:20:16 +0000 (16:20 -0500)
If the attempt to instantiate the mirror's layout DS pointer failed,
then that pointer may hold a value of type ERR_PTR(), so we need
to check that before we dereference it.

Fixes: eae9c36784e47 ("pNFS/flexfiles: Fix a deadlock on LAYOUTGET")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/flexfilelayout/flexfilelayout.h

index c2626bad466b22addbdf404ab462ec4df8c1f5f7..8a2d5d630af9d0a05da2ca574845c265a338ab4d 100644 (file)
@@ -132,16 +132,6 @@ FF_LAYOUT_LSEG(struct pnfs_layout_segment *lseg)
                            generic_hdr);
 }
 
-static inline struct nfs4_deviceid_node *
-FF_LAYOUT_DEVID_NODE(struct pnfs_layout_segment *lseg, u32 idx)
-{
-       if (idx >= FF_LAYOUT_LSEG(lseg)->mirror_array_cnt ||
-           FF_LAYOUT_LSEG(lseg)->mirror_array[idx] == NULL ||
-           FF_LAYOUT_LSEG(lseg)->mirror_array[idx]->mirror_ds == NULL)
-               return NULL;
-       return &FF_LAYOUT_LSEG(lseg)->mirror_array[idx]->mirror_ds->id_node;
-}
-
 static inline struct nfs4_ff_layout_ds *
 FF_LAYOUT_MIRROR_DS(struct nfs4_deviceid_node *node)
 {
@@ -151,9 +141,25 @@ FF_LAYOUT_MIRROR_DS(struct nfs4_deviceid_node *node)
 static inline struct nfs4_ff_layout_mirror *
 FF_LAYOUT_COMP(struct pnfs_layout_segment *lseg, u32 idx)
 {
-       if (idx >= FF_LAYOUT_LSEG(lseg)->mirror_array_cnt)
-               return NULL;
-       return FF_LAYOUT_LSEG(lseg)->mirror_array[idx];
+       struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
+
+       if (idx < fls->mirror_array_cnt)
+               return fls->mirror_array[idx];
+       return NULL;
+}
+
+static inline struct nfs4_deviceid_node *
+FF_LAYOUT_DEVID_NODE(struct pnfs_layout_segment *lseg, u32 idx)
+{
+       struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, idx);
+
+       if (mirror != NULL) {
+               struct nfs4_ff_layout_ds *mirror_ds = mirror->mirror_ds;
+
+               if (!IS_ERR_OR_NULL(mirror_ds))
+                       return &mirror_ds->id_node;
+       }
+       return NULL;
 }
 
 static inline u32