Unified · Split
| @@ -935,6 +935,81 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, · 934 unmodified lines | ||
| 935 | 935 | return ret; |
| 936 | 936 | } |
| 937 | 937 | |
| 938 | +/* | |
| 939 | + * Use mdsthreshold hints set at each OPEN to determine if I/O should go | |
| 940 | + * to the MDS or over pNFS | |
| 941 | + * | |
| 942 | + * The nfs_inode read_io and write_io fields are cumulative counters reset | |
| 943 | + * when there are no layout segments. Note that in pnfs_update_layout iomode | |
| 944 | + * is set to IOMODE_READ for a READ request, and set to IOMODE_RW for a | |
| 945 | + * WRITE request. | |
| 946 | + * | |
| 947 | + * A return of true means use MDS I/O. | |
| 948 | + * | |
| 949 | + * From rfc 5661: | |
| 950 | + * If a file's size is smaller than the file size threshold, data accesses | |
| 951 | + * SHOULD be sent to the metadata server. If an I/O request has a length that | |
| 952 | + * is below the I/O size threshold, the I/O SHOULD be sent to the metadata | |
| 953 | + * server. If both file size and I/O size are provided, the client SHOULD | |
| 954 | + * reach or exceed both thresholds before sending its read or write | |
| 955 | + * requests to the data server. | |
| 956 | + */ | |
| 957 | +static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx, | |
| 958 | + struct inode *ino, int iomode) | |
| 959 | +{ | |
| 960 | + struct nfs4_threshold *t = ctx->mdsthreshold; | |
| 961 | + struct nfs_inode *nfsi = NFS_I(ino); | |
| 962 | + loff_t fsize = i_size_read(ino); | |
| 963 | + bool size = false, size_set = false, io = false, io_set = false, ret = false; | |
| 964 | + | |
| 965 | + if (t == NULL) | |
| 966 | + return ret; | |
| 967 | + | |
| 968 | + dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n", | |
| 969 | + __func__, t->bm, t->rd_sz, t->wr_sz, t->rd_io_sz, t->wr_io_sz); | |
| 970 | + | |
| 971 | + switch (iomode) { | |
| 972 | + case IOMODE_READ: | |
| 973 | + if (t->bm & THRESHOLD_RD) { | |
| 974 | + dprintk("%s fsize %llu\n", __func__, fsize); | |
| 975 | + size_set = true; | |
| 976 | + if (fsize < t->rd_sz) | |
| 977 | + size = true; | |
| 978 | + } | |
| 979 | + if (t->bm & THRESHOLD_RD_IO) { | |
| 980 | + dprintk("%s nfsi->read_io %llu\n", __func__, | |
| 981 | + nfsi->read_io); | |
| 982 | + io_set = true; | |
| 983 | + if (nfsi->read_io < t->rd_io_sz) | |
| 984 | + io = true; | |
| 985 | + } | |
| 986 | + break; | |
| 987 | + case IOMODE_RW: | |
| 988 | + if (t->bm & THRESHOLD_WR) { | |
| 989 | + dprintk("%s fsize %llu\n", __func__, fsize); | |
| 990 | + size_set = true; | |
| 991 | + if (fsize < t->wr_sz) | |
| 992 | + size = true; | |
| 993 | + } | |
| 994 | + if (t->bm & THRESHOLD_WR_IO) { | |
| 995 | + dprintk("%s nfsi->write_io %llu\n", __func__, | |
| 996 | + nfsi->write_io); | |
| 997 | + io_set = true; | |
| 998 | + if (nfsi->write_io < t->wr_io_sz) | |
| 999 | + io = true; | |
| 1000 | + } | |
| 1001 | + break; | |
| 1002 | + } | |
| 1003 | + if (size_set && io_set) { | |
| 1004 | + if (size && io) | |
| 1005 | + ret = true; | |
| 1006 | + } else if (size || io) | |
| 1007 | + ret = true; | |
| 1008 | + | |
| 1009 | + dprintk("<-- %s size %d io %d ret %d\n", __func__, size, io, ret); | |
| 1010 | + return ret; | |
| 1011 | +} | |
| 1012 | + | |
| 938 | 1013 | /* |
| 939 | 1014 | * Layout segment is retreived from the server if not cached. |
| 940 | 1015 | * The appropriate layout segment is referenced and returned to the caller. |
| @@ -962,6 +1037,10 @@ pnfs_update_layout(struct inode *ino, · 21 unmodified lines | ||
| 962 | 1037 | |
| 963 | 1038 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) |
| 964 | 1039 | return NULL; |
| 1040 | + | |
| 1041 | + if (pnfs_within_mdsthreshold(ctx, ino, iomode)) | |
| 1042 | + return NULL; | |
| 1043 | + | |
| 965 | 1044 | spin_lock(&ino->i_lock); |
| 966 | 1045 | lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags); |
| 967 | 1046 | if (lo == NULL) { |