Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSv4.1/flexfile: Ensure uniqueness of mirrors across layout segments

Keep the full list of mirrors in the struct nfs4_ff_layout_mirror so that
they can be shared among the layout segments that use them.
Also ensure that we send out only one copy of the layoutstats per mirror.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>

+99 -29
+96 -29
fs/nfs/flexfilelayout/flexfilelayout.c
··· 34 34 ffl = kzalloc(sizeof(*ffl), gfp_flags); 35 35 if (ffl) { 36 36 INIT_LIST_HEAD(&ffl->error_list); 37 + INIT_LIST_HEAD(&ffl->mirrors); 37 38 return &ffl->generic_hdr; 38 39 } else 39 40 return NULL; ··· 136 135 return 0; 137 136 } 138 137 138 + static bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1, 139 + const struct nfs4_ff_layout_mirror *m2) 140 + { 141 + int i, j; 142 + 143 + if (m1->fh_versions_cnt != m2->fh_versions_cnt) 144 + return false; 145 + for (i = 0; i < m1->fh_versions_cnt; i++) { 146 + bool found_fh = false; 147 + for (j = 0; j < m2->fh_versions_cnt; i++) { 148 + if (nfs_compare_fh(&m1->fh_versions[i], 149 + &m2->fh_versions[j]) == 0) { 150 + found_fh = true; 151 + break; 152 + } 153 + } 154 + if (!found_fh) 155 + return false; 156 + } 157 + return true; 158 + } 159 + 160 + static struct nfs4_ff_layout_mirror * 161 + ff_layout_add_mirror(struct pnfs_layout_hdr *lo, 162 + struct nfs4_ff_layout_mirror *mirror) 163 + { 164 + struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(lo); 165 + struct nfs4_ff_layout_mirror *pos; 166 + struct inode *inode = lo->plh_inode; 167 + 168 + spin_lock(&inode->i_lock); 169 + list_for_each_entry(pos, &ff_layout->mirrors, mirrors) { 170 + if (mirror->mirror_ds != pos->mirror_ds) 171 + continue; 172 + if (!ff_mirror_match_fh(mirror, pos)) 173 + continue; 174 + if (atomic_inc_not_zero(&pos->ref)) { 175 + spin_unlock(&inode->i_lock); 176 + return pos; 177 + } 178 + } 179 + list_add(&mirror->mirrors, &ff_layout->mirrors); 180 + mirror->layout = lo; 181 + spin_unlock(&inode->i_lock); 182 + return mirror; 183 + } 184 + 185 + void 186 + ff_layout_remove_mirror(struct nfs4_ff_layout_mirror *mirror) 187 + { 188 + struct inode *inode; 189 + if (mirror->layout == NULL) 190 + return; 191 + inode = mirror->layout->plh_inode; 192 + spin_lock(&inode->i_lock); 193 + list_del(&mirror->mirrors); 194 + spin_unlock(&inode->i_lock); 195 + mirror->layout = NULL; 196 + } 197 + 139 198 static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags) 140 199 { 141 200 struct nfs4_ff_layout_mirror *mirror; ··· 204 143 if (mirror != NULL) { 205 144 spin_lock_init(&mirror->lock); 206 145 atomic_set(&mirror->ref, 1); 146 + INIT_LIST_HEAD(&mirror->mirrors); 207 147 } 208 148 return mirror; 209 149 } 210 150 211 151 static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror) 212 152 { 153 + ff_layout_remove_mirror(mirror); 213 154 kfree(mirror->fh_versions); 214 155 nfs4_ff_layout_put_deviceid(mirror->mirror_ds); 215 156 kfree(mirror); ··· 330 267 goto out_err_free; 331 268 332 269 for (i = 0; i < fls->mirror_array_cnt; i++) { 270 + struct nfs4_ff_layout_mirror *mirror; 333 271 struct nfs4_deviceid devid; 334 272 struct nfs4_deviceid_node *idnode; 335 273 u32 ds_count; ··· 418 354 rc = decode_name(&stream, &fls->mirror_array[i]->gid); 419 355 if (rc) 420 356 goto out_err_free; 357 + 358 + mirror = ff_layout_add_mirror(lh, fls->mirror_array[i]); 359 + if (mirror != fls->mirror_array[i]) { 360 + ff_layout_free_mirror(fls->mirror_array[i]); 361 + fls->mirror_array[i] = mirror; 362 + } 421 363 422 364 dprintk("%s: uid %d gid %d\n", __func__, 423 365 fls->mirror_array[i]->uid, ··· 1953 1883 *start = cpu_to_be32((xdr->p - start - 1) * 4); 1954 1884 } 1955 1885 1956 - static bool 1886 + static int 1957 1887 ff_layout_mirror_prepare_stats(struct nfs42_layoutstat_args *args, 1958 - struct pnfs_layout_segment *pls, 1959 - int *dev_count, int dev_limit) 1888 + struct pnfs_layout_hdr *lo, 1889 + int dev_limit) 1960 1890 { 1891 + struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(lo); 1961 1892 struct nfs4_ff_layout_mirror *mirror; 1962 1893 struct nfs4_deviceid_node *dev; 1963 1894 struct nfs42_layoutstat_devinfo *devinfo; 1964 - int i; 1895 + int i = 0; 1965 1896 1966 - for (i = 0; i < FF_LAYOUT_MIRROR_COUNT(pls); i++) { 1967 - if (*dev_count >= dev_limit) 1897 + list_for_each_entry(mirror, &ff_layout->mirrors, mirrors) { 1898 + if (i >= dev_limit) 1968 1899 break; 1969 - mirror = FF_LAYOUT_COMP(pls, i); 1970 - if (!mirror || !mirror->mirror_ds) 1900 + if (!mirror->mirror_ds) 1971 1901 continue; 1972 - dev = FF_LAYOUT_DEVID_NODE(pls, i); 1973 - devinfo = &args->devinfo[*dev_count]; 1902 + /* mirror refcount put in cleanup_layoutstats */ 1903 + if (!atomic_inc_not_zero(&mirror->ref)) 1904 + continue; 1905 + dev = &mirror->mirror_ds->id_node; 1906 + devinfo = &args->devinfo[i]; 1974 1907 memcpy(&devinfo->dev_id, &dev->deviceid, NFS4_DEVICEID4_SIZE); 1975 - devinfo->offset = pls->pls_range.offset; 1976 - devinfo->length = pls->pls_range.length; 1908 + devinfo->offset = 0; 1909 + devinfo->length = NFS4_MAX_UINT64; 1977 1910 devinfo->read_count = mirror->read_stat.io_stat.ops_completed; 1978 1911 devinfo->read_bytes = mirror->read_stat.io_stat.bytes_completed; 1979 1912 devinfo->write_count = mirror->write_stat.io_stat.ops_completed; ··· 1984 1911 devinfo->layout_type = LAYOUT_FLEX_FILES; 1985 1912 devinfo->layoutstats_encode = ff_layout_encode_layoutstats; 1986 1913 devinfo->layout_private = mirror; 1987 - /* mirror refcount put in cleanup_layoutstats */ 1988 - atomic_inc(&mirror->ref); 1989 1914 1990 - ++(*dev_count); 1915 + i++; 1991 1916 } 1992 - 1993 - return *dev_count < dev_limit; 1917 + return i; 1994 1918 } 1995 1919 1996 1920 static int 1997 1921 ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args) 1998 1922 { 1999 - struct pnfs_layout_segment *pls; 1923 + struct nfs4_flexfile_layout *ff_layout; 1924 + struct nfs4_ff_layout_mirror *mirror; 2000 1925 int dev_count = 0; 2001 1926 2002 1927 spin_lock(&args->inode->i_lock); 2003 - list_for_each_entry(pls, &NFS_I(args->inode)->layout->plh_segs, pls_list) { 2004 - dev_count += FF_LAYOUT_MIRROR_COUNT(pls); 1928 + ff_layout = FF_LAYOUT_FROM_HDR(NFS_I(args->inode)->layout); 1929 + list_for_each_entry(mirror, &ff_layout->mirrors, mirrors) { 1930 + if (atomic_read(&mirror->ref) != 0) 1931 + dev_count ++; 2005 1932 } 2006 1933 spin_unlock(&args->inode->i_lock); 2007 1934 /* For now, send at most PNFS_LAYOUTSTATS_MAXDEV statistics */ ··· 2010 1937 __func__, dev_count, PNFS_LAYOUTSTATS_MAXDEV); 2011 1938 dev_count = PNFS_LAYOUTSTATS_MAXDEV; 2012 1939 } 2013 - args->devinfo = kmalloc(dev_count * sizeof(*args->devinfo), GFP_KERNEL); 1940 + args->devinfo = kmalloc_array(dev_count, sizeof(*args->devinfo), GFP_NOIO); 2014 1941 if (!args->devinfo) 2015 1942 return -ENOMEM; 2016 1943 2017 - dev_count = 0; 2018 1944 spin_lock(&args->inode->i_lock); 2019 - list_for_each_entry(pls, &NFS_I(args->inode)->layout->plh_segs, pls_list) { 2020 - if (!ff_layout_mirror_prepare_stats(args, pls, &dev_count, 2021 - PNFS_LAYOUTSTATS_MAXDEV)) { 2022 - break; 2023 - } 2024 - } 1945 + args->num_dev = ff_layout_mirror_prepare_stats(args, 1946 + &ff_layout->generic_hdr, dev_count); 2025 1947 spin_unlock(&args->inode->i_lock); 2026 - args->num_dev = dev_count; 2027 1948 2028 1949 return 0; 2029 1950 }
+3
fs/nfs/flexfilelayout/flexfilelayout.h
··· 67 67 }; 68 68 69 69 struct nfs4_ff_layout_mirror { 70 + struct pnfs_layout_hdr *layout; 71 + struct list_head mirrors; 70 72 u32 ds_count; 71 73 u32 efficiency; 72 74 struct nfs4_ff_layout_ds *mirror_ds; ··· 97 95 struct nfs4_flexfile_layout { 98 96 struct pnfs_layout_hdr generic_hdr; 99 97 struct pnfs_ds_commit_info commit_info; 98 + struct list_head mirrors; 100 99 struct list_head error_list; /* nfs4_ff_layout_ds_err */ 101 100 }; 102 101