ktime: Get rid of the union
[linux-2.6-block.git] / fs / nfs / flexfilelayout / flexfilelayout.c
index e5078301720acab74075755e07e23e7e28bf4374..c98f6db9aa6bdd6ccb89d016a1b744ff92dff595 100644 (file)
@@ -32,6 +32,12 @@ static struct group_info     *ff_zero_group;
 
 static void ff_layout_read_record_layoutstats_done(struct rpc_task *task,
                struct nfs_pgio_header *hdr);
+static int ff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo,
+                              struct nfs42_layoutstat_devinfo *devinfo,
+                              int dev_limit);
+static void ff_layout_encode_ff_layoutupdate(struct xdr_stream *xdr,
+                             const struct nfs42_layoutstat_devinfo *devinfo,
+                             struct nfs4_ff_layout_mirror *mirror);
 
 static struct pnfs_layout_hdr *
 ff_layout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
@@ -177,7 +183,7 @@ ff_layout_add_mirror(struct pnfs_layout_hdr *lo,
 
        spin_lock(&inode->i_lock);
        list_for_each_entry(pos, &ff_layout->mirrors, mirrors) {
-               if (mirror->mirror_ds != pos->mirror_ds)
+               if (memcmp(&mirror->devid, &pos->devid, sizeof(pos->devid)) != 0)
                        continue;
                if (!ff_mirror_match_fh(mirror, pos))
                        continue;
@@ -354,19 +360,6 @@ static void ff_layout_sort_mirrors(struct nfs4_ff_layout_segment *fls)
        }
 }
 
-static void ff_layout_mark_devices_valid(struct nfs4_ff_layout_segment *fls)
-{
-       struct nfs4_deviceid_node *node;
-       int i;
-
-       if (!(fls->flags & FF_FLAGS_NO_IO_THRU_MDS))
-               return;
-       for (i = 0; i < fls->mirror_array_cnt; i++) {
-               node = &fls->mirror_array[i]->mirror_ds->id_node;
-               clear_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags);
-       }
-}
-
 static struct pnfs_layout_segment *
 ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
                     struct nfs4_layoutget_res *lgr,
@@ -420,8 +413,6 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
 
        for (i = 0; i < fls->mirror_array_cnt; i++) {
                struct nfs4_ff_layout_mirror *mirror;
-               struct nfs4_deviceid devid;
-               struct nfs4_deviceid_node *idnode;
                struct auth_cred acred = { .group_info = ff_zero_group };
                struct rpc_cred __rcu *cred;
                u32 ds_count, fh_count, id;
@@ -446,24 +437,10 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
                fls->mirror_array[i]->ds_count = ds_count;
 
                /* deviceid */
-               rc = decode_deviceid(&stream, &devid);
+               rc = decode_deviceid(&stream, &fls->mirror_array[i]->devid);
                if (rc)
                        goto out_err_free;
 
-               idnode = nfs4_find_get_deviceid(NFS_SERVER(lh->plh_inode),
-                                               &devid, lh->plh_lc_cred,
-                                               gfp_flags);
-               /*
-                * upon success, mirror_ds is allocated by previous
-                * getdeviceinfo, or newly by .alloc_deviceid_node
-                * nfs4_find_get_deviceid failure is indeed getdeviceinfo falure
-                */
-               if (idnode)
-                       fls->mirror_array[i]->mirror_ds =
-                               FF_LAYOUT_MIRROR_DS(idnode);
-               else
-                       goto out_err_free;
-
                /* efficiency */
                rc = -EIO;
                p = xdr_inline_decode(&stream, 4);
@@ -561,8 +538,6 @@ out_sort_mirrors:
        rc = ff_layout_check_layout(lgr);
        if (rc)
                goto out_err_free;
-       ff_layout_mark_devices_valid(fls);
-
        ret = &fls->generic_hdr;
        dprintk("<-- %s (success)\n", __func__);
 out_free_page:
@@ -644,12 +619,11 @@ nfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_mirror *mirror,
                            struct nfs4_ff_layoutstat *layoutstat,
                            ktime_t now)
 {
-       static const ktime_t notime = {0};
        s64 report_interval = FF_LAYOUTSTATS_REPORT_INTERVAL;
        struct nfs4_flexfile_layout *ffl = FF_LAYOUT_FROM_HDR(mirror->layout);
 
        nfs4_ff_start_busy_timer(&layoutstat->busy_timer, now);
-       if (ktime_equal(mirror->start_time, notime))
+       if (ktime_equal(mirror->start_time, 0))
                mirror->start_time = now;
        if (mirror->report_interval != 0)
                report_interval = (s64)mirror->report_interval * 1000LL;
@@ -1151,7 +1125,8 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
        case -EPIPE:
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
-               nfs4_mark_deviceid_unavailable(devid);
+               nfs4_delete_deviceid(devid->ld, devid->nfs_client,
+                               &devid->deviceid);
                rpc_wake_up(&tbl->slot_tbl_waitq);
                /* fall through */
        default:
@@ -1200,7 +1175,8 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task,
        default:
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
-               nfs4_mark_deviceid_unavailable(devid);
+               nfs4_delete_deviceid(devid->ld, devid->nfs_client,
+                               &devid->deviceid);
        }
        /* FIXME: Need to prevent infinite looping here. */
        return -NFS4ERR_RESET_TO_PNFS;
@@ -1971,8 +1947,7 @@ ff_layout_free_deviceid_node(struct nfs4_deviceid_node *d)
                                                  id_node));
 }
 
-static int ff_layout_encode_ioerr(struct nfs4_flexfile_layout *flo,
-                                 struct xdr_stream *xdr,
+static int ff_layout_encode_ioerr(struct xdr_stream *xdr,
                                  const struct nfs4_layoutreturn_args *args,
                                  const struct nfs4_flexfile_layoutreturn_args *ff_args)
 {
@@ -1987,16 +1962,73 @@ static int ff_layout_encode_ioerr(struct nfs4_flexfile_layout *flo,
        return ff_layout_encode_ds_ioerr(xdr, &ff_args->errors);
 }
 
+static void
+encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, len);
+       xdr_encode_opaque_fixed(p, buf, len);
+}
+
+static void
+ff_layout_encode_ff_iostat_head(struct xdr_stream *xdr,
+                           const nfs4_stateid *stateid,
+                           const struct nfs42_layoutstat_devinfo *devinfo)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, 8 + 8);
+       p = xdr_encode_hyper(p, devinfo->offset);
+       p = xdr_encode_hyper(p, devinfo->length);
+       encode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE);
+       p = xdr_reserve_space(xdr, 4*8);
+       p = xdr_encode_hyper(p, devinfo->read_count);
+       p = xdr_encode_hyper(p, devinfo->read_bytes);
+       p = xdr_encode_hyper(p, devinfo->write_count);
+       p = xdr_encode_hyper(p, devinfo->write_bytes);
+       encode_opaque_fixed(xdr, devinfo->dev_id.data, NFS4_DEVICEID4_SIZE);
+}
+
+static void
+ff_layout_encode_ff_iostat(struct xdr_stream *xdr,
+                           const nfs4_stateid *stateid,
+                           const struct nfs42_layoutstat_devinfo *devinfo)
+{
+       ff_layout_encode_ff_iostat_head(xdr, stateid, devinfo);
+       ff_layout_encode_ff_layoutupdate(xdr, devinfo,
+                       devinfo->ld_private.data);
+}
+
 /* report nothing for now */
-static void ff_layout_encode_iostats_array(struct nfs4_flexfile_layout *flo,
-                                    struct xdr_stream *xdr,
-                                    const struct nfs4_layoutreturn_args *args)
+static void ff_layout_encode_iostats_array(struct xdr_stream *xdr,
+               const struct nfs4_layoutreturn_args *args,
+               struct nfs4_flexfile_layoutreturn_args *ff_args)
 {
        __be32 *p;
+       int i;
 
        p = xdr_reserve_space(xdr, 4);
-       if (likely(p))
-               *p = cpu_to_be32(0);
+       *p = cpu_to_be32(ff_args->num_dev);
+       for (i = 0; i < ff_args->num_dev; i++)
+               ff_layout_encode_ff_iostat(xdr,
+                               &args->layout->plh_stateid,
+                               &ff_args->devinfo[i]);
+}
+
+static void
+ff_layout_free_iostats_array(struct nfs42_layoutstat_devinfo *devinfo,
+               unsigned int num_entries)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_entries; i++) {
+               if (!devinfo[i].ld_private.ops)
+                       continue;
+               if (!devinfo[i].ld_private.ops->free)
+                       continue;
+               devinfo[i].ld_private.ops->free(&devinfo[i].ld_private);
+       }
 }
 
 static struct nfs4_deviceid_node *
@@ -2017,18 +2049,29 @@ ff_layout_encode_layoutreturn(struct xdr_stream *xdr,
                const struct nfs4_xdr_opaque_data *ff_opaque)
 {
        const struct nfs4_layoutreturn_args *args = voidargs;
-       struct pnfs_layout_hdr *lo = args->layout;
-       struct nfs4_flexfile_layout *flo = FF_LAYOUT_FROM_HDR(lo);
+       struct nfs4_flexfile_layoutreturn_args *ff_args = ff_opaque->data;
+       struct xdr_buf tmp_buf = {
+               .head = {
+                       [0] = {
+                               .iov_base = page_address(ff_args->pages[0]),
+                       },
+               },
+               .buflen = PAGE_SIZE,
+       };
+       struct xdr_stream tmp_xdr;
        __be32 *start;
 
        dprintk("%s: Begin\n", __func__);
-       start = xdr_reserve_space(xdr, 4);
-       BUG_ON(!start);
 
-       ff_layout_encode_ioerr(flo, xdr, args, ff_opaque->data);
-       ff_layout_encode_iostats_array(flo, xdr, args);
+       xdr_init_encode(&tmp_xdr, &tmp_buf, NULL);
+
+       ff_layout_encode_ioerr(&tmp_xdr, args, ff_args);
+       ff_layout_encode_iostats_array(&tmp_xdr, args, ff_args);
+
+       start = xdr_reserve_space(xdr, 4);
+       *start = cpu_to_be32(tmp_buf.len);
+       xdr_write_pages(xdr, ff_args->pages, 0, tmp_buf.len);
 
-       *start = cpu_to_be32((xdr->p - start - 1) * 4);
        dprintk("%s: Return\n", __func__);
 }
 
@@ -2043,7 +2086,9 @@ ff_layout_free_layoutreturn(struct nfs4_xdr_opaque_data *args)
        args->data = NULL;
 
        ff_layout_free_ds_ioerr(&ff_args->errors);
+       ff_layout_free_iostats_array(ff_args->devinfo, ff_args->num_dev);
 
+       put_page(ff_args->pages[0]);
        kfree(ff_args);
 }
 
@@ -2056,19 +2101,32 @@ static int
 ff_layout_prepare_layoutreturn(struct nfs4_layoutreturn_args *args)
 {
        struct nfs4_flexfile_layoutreturn_args *ff_args;
+       struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(args->layout);
 
        ff_args = kmalloc(sizeof(*ff_args), GFP_KERNEL);
        if (!ff_args)
-               return -ENOMEM;
+               goto out_nomem;
+       ff_args->pages[0] = alloc_page(GFP_KERNEL);
+       if (!ff_args->pages[0])
+               goto out_nomem_free;
 
        INIT_LIST_HEAD(&ff_args->errors);
        ff_args->num_errors = ff_layout_fetch_ds_ioerr(args->layout,
                        &args->range, &ff_args->errors,
                        FF_LAYOUTRETURN_MAXERR);
 
+       spin_lock(&args->inode->i_lock);
+       ff_args->num_dev = ff_layout_mirror_prepare_stats(&ff_layout->generic_hdr,
+                       &ff_args->devinfo[0], ARRAY_SIZE(ff_args->devinfo));
+       spin_unlock(&args->inode->i_lock);
+
        args->ld_private->ops = &layoutreturn_ops;
        args->ld_private->data = ff_args;
        return 0;
+out_nomem_free:
+       kfree(ff_args);
+out_nomem:
+       return -ENOMEM;
 }
 
 static int
@@ -2262,7 +2320,7 @@ ff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo,
        list_for_each_entry(mirror, &ff_layout->mirrors, mirrors) {
                if (i >= dev_limit)
                        break;
-               if (!mirror->mirror_ds)
+               if (IS_ERR_OR_NULL(mirror->mirror_ds))
                        continue;
                if (!test_and_clear_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags))
                        continue;