LCOV - code coverage report
Current view: top level - fs/nfs - nfs42proc.c (source / functions) Hit Total Coverage
Test: Real Lines: 0 383 0.0 %
Date: 2020-10-17 15:46:16 Functions: 0 26 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
       4                 :            :  */
       5                 :            : #include <linux/fs.h>
       6                 :            : #include <linux/sunrpc/sched.h>
       7                 :            : #include <linux/nfs.h>
       8                 :            : #include <linux/nfs3.h>
       9                 :            : #include <linux/nfs4.h>
      10                 :            : #include <linux/nfs_xdr.h>
      11                 :            : #include <linux/nfs_fs.h>
      12                 :            : #include "nfs4_fs.h"
      13                 :            : #include "nfs42.h"
      14                 :            : #include "iostat.h"
      15                 :            : #include "pnfs.h"
      16                 :            : #include "nfs4session.h"
      17                 :            : #include "internal.h"
      18                 :            : 
      19                 :            : #define NFSDBG_FACILITY NFSDBG_PROC
      20                 :            : static int nfs42_do_offload_cancel_async(struct file *dst, nfs4_stateid *std);
      21                 :            : 
      22                 :          0 : static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
      23                 :            :                 struct nfs_lock_context *lock, loff_t offset, loff_t len)
      24                 :            : {
      25                 :            :         struct inode *inode = file_inode(filep);
      26                 :            :         struct nfs_server *server = NFS_SERVER(inode);
      27                 :          0 :         struct nfs42_falloc_args args = {
      28                 :            :                 .falloc_fh      = NFS_FH(inode),
      29                 :            :                 .falloc_offset  = offset,
      30                 :            :                 .falloc_length  = len,
      31                 :          0 :                 .falloc_bitmask = server->cache_consistency_bitmask,
      32                 :            :         };
      33                 :          0 :         struct nfs42_falloc_res res = {
      34                 :            :                 .falloc_server  = server,
      35                 :            :         };
      36                 :            :         int status;
      37                 :            : 
      38                 :          0 :         msg->rpc_argp = &args;
      39                 :          0 :         msg->rpc_resp = &res;
      40                 :            : 
      41                 :          0 :         status = nfs4_set_rw_stateid(&args.falloc_stateid, lock->open_context,
      42                 :            :                         lock, FMODE_WRITE);
      43                 :          0 :         if (status)
      44                 :            :                 return status;
      45                 :            : 
      46                 :          0 :         res.falloc_fattr = nfs_alloc_fattr();
      47                 :          0 :         if (!res.falloc_fattr)
      48                 :            :                 return -ENOMEM;
      49                 :            : 
      50                 :          0 :         status = nfs4_call_sync(server->client, server, msg,
      51                 :            :                                 &args.seq_args, &res.seq_res, 0);
      52                 :          0 :         if (status == 0)
      53                 :          0 :                 status = nfs_post_op_update_inode(inode, res.falloc_fattr);
      54                 :            : 
      55                 :          0 :         kfree(res.falloc_fattr);
      56                 :          0 :         return status;
      57                 :            : }
      58                 :            : 
      59                 :          0 : static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
      60                 :            :                                 loff_t offset, loff_t len)
      61                 :            : {
      62                 :            :         struct nfs_server *server = NFS_SERVER(file_inode(filep));
      63                 :          0 :         struct nfs4_exception exception = { };
      64                 :            :         struct nfs_lock_context *lock;
      65                 :            :         int err;
      66                 :            : 
      67                 :          0 :         lock = nfs_get_lock_context(nfs_file_open_context(filep));
      68                 :          0 :         if (IS_ERR(lock))
      69                 :          0 :                 return PTR_ERR(lock);
      70                 :            : 
      71                 :          0 :         exception.inode = file_inode(filep);
      72                 :          0 :         exception.state = lock->open_context->state;
      73                 :            : 
      74                 :            :         do {
      75                 :          0 :                 err = _nfs42_proc_fallocate(msg, filep, lock, offset, len);
      76                 :          0 :                 if (err == -ENOTSUPP) {
      77                 :            :                         err = -EOPNOTSUPP;
      78                 :            :                         break;
      79                 :            :                 }
      80                 :          0 :                 err = nfs4_handle_exception(server, err, &exception);
      81                 :          0 :         } while (exception.retry);
      82                 :            : 
      83                 :          0 :         nfs_put_lock_context(lock);
      84                 :          0 :         return err;
      85                 :            : }
      86                 :            : 
      87                 :          0 : int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len)
      88                 :            : {
      89                 :          0 :         struct rpc_message msg = {
      90                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE],
      91                 :            :         };
      92                 :            :         struct inode *inode = file_inode(filep);
      93                 :            :         int err;
      94                 :            : 
      95                 :          0 :         if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE))
      96                 :            :                 return -EOPNOTSUPP;
      97                 :            : 
      98                 :            :         inode_lock(inode);
      99                 :            : 
     100                 :          0 :         err = nfs42_proc_fallocate(&msg, filep, offset, len);
     101                 :          0 :         if (err == -EOPNOTSUPP)
     102                 :          0 :                 NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE;
     103                 :            : 
     104                 :            :         inode_unlock(inode);
     105                 :          0 :         return err;
     106                 :            : }
     107                 :            : 
     108                 :          0 : int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
     109                 :            : {
     110                 :          0 :         struct rpc_message msg = {
     111                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DEALLOCATE],
     112                 :            :         };
     113                 :            :         struct inode *inode = file_inode(filep);
     114                 :            :         int err;
     115                 :            : 
     116                 :          0 :         if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE))
     117                 :            :                 return -EOPNOTSUPP;
     118                 :            : 
     119                 :            :         inode_lock(inode);
     120                 :          0 :         err = nfs_sync_inode(inode);
     121                 :          0 :         if (err)
     122                 :            :                 goto out_unlock;
     123                 :            : 
     124                 :          0 :         err = nfs42_proc_fallocate(&msg, filep, offset, len);
     125                 :          0 :         if (err == 0)
     126                 :          0 :                 truncate_pagecache_range(inode, offset, (offset + len) -1);
     127                 :          0 :         if (err == -EOPNOTSUPP)
     128                 :          0 :                 NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE;
     129                 :            : out_unlock:
     130                 :            :         inode_unlock(inode);
     131                 :          0 :         return err;
     132                 :            : }
     133                 :            : 
     134                 :          0 : static int handle_async_copy(struct nfs42_copy_res *res,
     135                 :            :                              struct nfs_server *server,
     136                 :            :                              struct file *src,
     137                 :            :                              struct file *dst,
     138                 :            :                              nfs4_stateid *src_stateid)
     139                 :            : {
     140                 :            :         struct nfs4_copy_state *copy, *tmp_copy;
     141                 :            :         int status = NFS4_OK;
     142                 :            :         bool found_pending = false;
     143                 :            :         struct nfs_open_context *ctx = nfs_file_open_context(dst);
     144                 :            : 
     145                 :          0 :         copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
     146                 :          0 :         if (!copy)
     147                 :            :                 return -ENOMEM;
     148                 :            : 
     149                 :          0 :         spin_lock(&server->nfs_client->cl_lock);
     150                 :          0 :         list_for_each_entry(tmp_copy, &server->nfs_client->pending_cb_stateids,
     151                 :            :                                 copies) {
     152                 :          0 :                 if (memcmp(&res->write_res.stateid, &tmp_copy->stateid,
     153                 :            :                                 NFS4_STATEID_SIZE))
     154                 :          0 :                         continue;
     155                 :            :                 found_pending = true;
     156                 :            :                 list_del(&tmp_copy->copies);
     157                 :            :                 break;
     158                 :            :         }
     159                 :          0 :         if (found_pending) {
     160                 :          0 :                 spin_unlock(&server->nfs_client->cl_lock);
     161                 :          0 :                 kfree(copy);
     162                 :          0 :                 copy = tmp_copy;
     163                 :          0 :                 goto out;
     164                 :            :         }
     165                 :            : 
     166                 :          0 :         memcpy(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
     167                 :            :         init_completion(&copy->completion);
     168                 :          0 :         copy->parent_state = ctx->state;
     169                 :            : 
     170                 :          0 :         list_add_tail(&copy->copies, &server->ss_copies);
     171                 :          0 :         spin_unlock(&server->nfs_client->cl_lock);
     172                 :            : 
     173                 :          0 :         status = wait_for_completion_interruptible(&copy->completion);
     174                 :          0 :         spin_lock(&server->nfs_client->cl_lock);
     175                 :            :         list_del_init(&copy->copies);
     176                 :          0 :         spin_unlock(&server->nfs_client->cl_lock);
     177                 :          0 :         if (status == -ERESTARTSYS) {
     178                 :            :                 goto out_cancel;
     179                 :          0 :         } else if (copy->flags) {
     180                 :            :                 status = -EAGAIN;
     181                 :            :                 goto out_cancel;
     182                 :            :         }
     183                 :            : out:
     184                 :          0 :         res->write_res.count = copy->count;
     185                 :          0 :         memcpy(&res->write_res.verifier, &copy->verf, sizeof(copy->verf));
     186                 :          0 :         status = -copy->error;
     187                 :            : 
     188                 :          0 :         kfree(copy);
     189                 :          0 :         return status;
     190                 :            : out_cancel:
     191                 :          0 :         nfs42_do_offload_cancel_async(dst, &copy->stateid);
     192                 :          0 :         kfree(copy);
     193                 :          0 :         return status;
     194                 :            : }
     195                 :            : 
     196                 :          0 : static int process_copy_commit(struct file *dst, loff_t pos_dst,
     197                 :            :                                struct nfs42_copy_res *res)
     198                 :            : {
     199                 :            :         struct nfs_commitres cres;
     200                 :            :         int status = -ENOMEM;
     201                 :            : 
     202                 :          0 :         cres.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
     203                 :          0 :         if (!cres.verf)
     204                 :            :                 goto out;
     205                 :            : 
     206                 :          0 :         status = nfs4_proc_commit(dst, pos_dst, res->write_res.count, &cres);
     207                 :          0 :         if (status)
     208                 :            :                 goto out_free;
     209                 :          0 :         if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
     210                 :          0 :                                     &cres.verf->verifier)) {
     211                 :            :                 dprintk("commit verf differs from copy verf\n");
     212                 :            :                 status = -EAGAIN;
     213                 :            :         }
     214                 :            : out_free:
     215                 :          0 :         kfree(cres.verf);
     216                 :            : out:
     217                 :          0 :         return status;
     218                 :            : }
     219                 :            : 
     220                 :          0 : static ssize_t _nfs42_proc_copy(struct file *src,
     221                 :            :                                 struct nfs_lock_context *src_lock,
     222                 :            :                                 struct file *dst,
     223                 :            :                                 struct nfs_lock_context *dst_lock,
     224                 :            :                                 struct nfs42_copy_args *args,
     225                 :            :                                 struct nfs42_copy_res *res)
     226                 :            : {
     227                 :          0 :         struct rpc_message msg = {
     228                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
     229                 :            :                 .rpc_argp = args,
     230                 :            :                 .rpc_resp = res,
     231                 :            :         };
     232                 :            :         struct inode *dst_inode = file_inode(dst);
     233                 :            :         struct nfs_server *server = NFS_SERVER(dst_inode);
     234                 :          0 :         loff_t pos_src = args->src_pos;
     235                 :          0 :         loff_t pos_dst = args->dst_pos;
     236                 :          0 :         size_t count = args->count;
     237                 :            :         ssize_t status;
     238                 :            : 
     239                 :          0 :         status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
     240                 :            :                                      src_lock, FMODE_READ);
     241                 :          0 :         if (status)
     242                 :            :                 return status;
     243                 :            : 
     244                 :          0 :         status = nfs_filemap_write_and_wait_range(file_inode(src)->i_mapping,
     245                 :          0 :                         pos_src, pos_src + (loff_t)count - 1);
     246                 :          0 :         if (status)
     247                 :            :                 return status;
     248                 :            : 
     249                 :          0 :         status = nfs4_set_rw_stateid(&args->dst_stateid, dst_lock->open_context,
     250                 :            :                                      dst_lock, FMODE_WRITE);
     251                 :          0 :         if (status)
     252                 :            :                 return status;
     253                 :            : 
     254                 :          0 :         status = nfs_sync_inode(dst_inode);
     255                 :          0 :         if (status)
     256                 :            :                 return status;
     257                 :            : 
     258                 :          0 :         res->commit_res.verf = NULL;
     259                 :          0 :         if (args->sync) {
     260                 :          0 :                 res->commit_res.verf =
     261                 :          0 :                         kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
     262                 :          0 :                 if (!res->commit_res.verf)
     263                 :            :                         return -ENOMEM;
     264                 :            :         }
     265                 :          0 :         set_bit(NFS_CLNT_DST_SSC_COPY_STATE,
     266                 :            :                 &dst_lock->open_context->state->flags);
     267                 :            : 
     268                 :          0 :         status = nfs4_call_sync(server->client, server, &msg,
     269                 :            :                                 &args->seq_args, &res->seq_res, 0);
     270                 :          0 :         if (status == -ENOTSUPP)
     271                 :          0 :                 server->caps &= ~NFS_CAP_COPY;
     272                 :          0 :         if (status)
     273                 :            :                 goto out;
     274                 :            : 
     275                 :          0 :         if (args->sync &&
     276                 :            :                 nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
     277                 :          0 :                                     &res->commit_res.verf->verifier)) {
     278                 :            :                 status = -EAGAIN;
     279                 :            :                 goto out;
     280                 :            :         }
     281                 :            : 
     282                 :          0 :         if (!res->synchronous) {
     283                 :          0 :                 status = handle_async_copy(res, server, src, dst,
     284                 :            :                                 &args->src_stateid);
     285                 :          0 :                 if (status)
     286                 :            :                         goto out;
     287                 :            :         }
     288                 :            : 
     289                 :          0 :         if ((!res->synchronous || !args->sync) &&
     290                 :          0 :                         res->write_res.verifier.committed != NFS_FILE_SYNC) {
     291                 :          0 :                 status = process_copy_commit(dst, pos_dst, res);
     292                 :          0 :                 if (status)
     293                 :            :                         goto out;
     294                 :            :         }
     295                 :            : 
     296                 :          0 :         truncate_pagecache_range(dst_inode, pos_dst,
     297                 :          0 :                                  pos_dst + res->write_res.count);
     298                 :            : 
     299                 :          0 :         status = res->write_res.count;
     300                 :            : out:
     301                 :          0 :         if (args->sync)
     302                 :          0 :                 kfree(res->commit_res.verf);
     303                 :          0 :         return status;
     304                 :            : }
     305                 :            : 
     306                 :          0 : ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
     307                 :            :                         struct file *dst, loff_t pos_dst,
     308                 :            :                         size_t count)
     309                 :            : {
     310                 :            :         struct nfs_server *server = NFS_SERVER(file_inode(dst));
     311                 :            :         struct nfs_lock_context *src_lock;
     312                 :            :         struct nfs_lock_context *dst_lock;
     313                 :          0 :         struct nfs42_copy_args args = {
     314                 :            :                 .src_fh         = NFS_FH(file_inode(src)),
     315                 :            :                 .src_pos        = pos_src,
     316                 :            :                 .dst_fh         = NFS_FH(file_inode(dst)),
     317                 :            :                 .dst_pos        = pos_dst,
     318                 :            :                 .count          = count,
     319                 :            :                 .sync           = false,
     320                 :            :         };
     321                 :            :         struct nfs42_copy_res res;
     322                 :          0 :         struct nfs4_exception src_exception = {
     323                 :            :                 .inode          = file_inode(src),
     324                 :            :                 .stateid        = &args.src_stateid,
     325                 :            :         };
     326                 :          0 :         struct nfs4_exception dst_exception = {
     327                 :            :                 .inode          = file_inode(dst),
     328                 :            :                 .stateid        = &args.dst_stateid,
     329                 :            :         };
     330                 :            :         ssize_t err, err2;
     331                 :            : 
     332                 :          0 :         src_lock = nfs_get_lock_context(nfs_file_open_context(src));
     333                 :          0 :         if (IS_ERR(src_lock))
     334                 :          0 :                 return PTR_ERR(src_lock);
     335                 :            : 
     336                 :          0 :         src_exception.state = src_lock->open_context->state;
     337                 :            : 
     338                 :          0 :         dst_lock = nfs_get_lock_context(nfs_file_open_context(dst));
     339                 :          0 :         if (IS_ERR(dst_lock)) {
     340                 :            :                 err = PTR_ERR(dst_lock);
     341                 :          0 :                 goto out_put_src_lock;
     342                 :            :         }
     343                 :            : 
     344                 :          0 :         dst_exception.state = dst_lock->open_context->state;
     345                 :            : 
     346                 :            :         do {
     347                 :            :                 inode_lock(file_inode(dst));
     348                 :          0 :                 err = _nfs42_proc_copy(src, src_lock,
     349                 :            :                                 dst, dst_lock,
     350                 :            :                                 &args, &res);
     351                 :            :                 inode_unlock(file_inode(dst));
     352                 :            : 
     353                 :          0 :                 if (err >= 0)
     354                 :            :                         break;
     355                 :          0 :                 if (err == -ENOTSUPP) {
     356                 :            :                         err = -EOPNOTSUPP;
     357                 :            :                         break;
     358                 :          0 :                 } else if (err == -EAGAIN) {
     359                 :          0 :                         dst_exception.retry = 1;
     360                 :          0 :                         continue;
     361                 :          0 :                 } else if (err == -NFS4ERR_OFFLOAD_NO_REQS && !args.sync) {
     362                 :          0 :                         args.sync = true;
     363                 :          0 :                         dst_exception.retry = 1;
     364                 :          0 :                         continue;
     365                 :            :                 }
     366                 :            : 
     367                 :          0 :                 err2 = nfs4_handle_exception(server, err, &src_exception);
     368                 :          0 :                 err  = nfs4_handle_exception(server, err, &dst_exception);
     369                 :          0 :                 if (!err)
     370                 :            :                         err = err2;
     371                 :          0 :         } while (src_exception.retry || dst_exception.retry);
     372                 :            : 
     373                 :          0 :         nfs_put_lock_context(dst_lock);
     374                 :            : out_put_src_lock:
     375                 :          0 :         nfs_put_lock_context(src_lock);
     376                 :          0 :         return err;
     377                 :            : }
     378                 :            : 
     379                 :            : struct nfs42_offloadcancel_data {
     380                 :            :         struct nfs_server *seq_server;
     381                 :            :         struct nfs42_offload_status_args args;
     382                 :            :         struct nfs42_offload_status_res res;
     383                 :            : };
     384                 :            : 
     385                 :          0 : static void nfs42_offload_cancel_prepare(struct rpc_task *task, void *calldata)
     386                 :            : {
     387                 :            :         struct nfs42_offloadcancel_data *data = calldata;
     388                 :            : 
     389                 :          0 :         nfs4_setup_sequence(data->seq_server->nfs_client,
     390                 :            :                                 &data->args.osa_seq_args,
     391                 :            :                                 &data->res.osr_seq_res, task);
     392                 :          0 : }
     393                 :            : 
     394                 :          0 : static void nfs42_offload_cancel_done(struct rpc_task *task, void *calldata)
     395                 :            : {
     396                 :            :         struct nfs42_offloadcancel_data *data = calldata;
     397                 :            : 
     398                 :          0 :         nfs41_sequence_done(task, &data->res.osr_seq_res);
     399                 :          0 :         if (task->tk_status &&
     400                 :          0 :                 nfs4_async_handle_error(task, data->seq_server, NULL,
     401                 :            :                         NULL) == -EAGAIN)
     402                 :          0 :                 rpc_restart_call_prepare(task);
     403                 :          0 : }
     404                 :            : 
     405                 :          0 : static void nfs42_free_offloadcancel_data(void *data)
     406                 :            : {
     407                 :          0 :         kfree(data);
     408                 :          0 : }
     409                 :            : 
     410                 :            : static const struct rpc_call_ops nfs42_offload_cancel_ops = {
     411                 :            :         .rpc_call_prepare = nfs42_offload_cancel_prepare,
     412                 :            :         .rpc_call_done = nfs42_offload_cancel_done,
     413                 :            :         .rpc_release = nfs42_free_offloadcancel_data,
     414                 :            : };
     415                 :            : 
     416                 :          0 : static int nfs42_do_offload_cancel_async(struct file *dst,
     417                 :            :                                          nfs4_stateid *stateid)
     418                 :            : {
     419                 :            :         struct nfs_server *dst_server = NFS_SERVER(file_inode(dst));
     420                 :            :         struct nfs42_offloadcancel_data *data = NULL;
     421                 :            :         struct nfs_open_context *ctx = nfs_file_open_context(dst);
     422                 :            :         struct rpc_task *task;
     423                 :          0 :         struct rpc_message msg = {
     424                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OFFLOAD_CANCEL],
     425                 :          0 :                 .rpc_cred = ctx->cred,
     426                 :            :         };
     427                 :          0 :         struct rpc_task_setup task_setup_data = {
     428                 :          0 :                 .rpc_client = dst_server->client,
     429                 :            :                 .rpc_message = &msg,
     430                 :            :                 .callback_ops = &nfs42_offload_cancel_ops,
     431                 :            :                 .workqueue = nfsiod_workqueue,
     432                 :            :                 .flags = RPC_TASK_ASYNC,
     433                 :            :         };
     434                 :            :         int status;
     435                 :            : 
     436                 :          0 :         if (!(dst_server->caps & NFS_CAP_OFFLOAD_CANCEL))
     437                 :            :                 return -EOPNOTSUPP;
     438                 :            : 
     439                 :          0 :         data = kzalloc(sizeof(struct nfs42_offloadcancel_data), GFP_NOFS);
     440                 :          0 :         if (data == NULL)
     441                 :            :                 return -ENOMEM;
     442                 :            : 
     443                 :          0 :         data->seq_server = dst_server;
     444                 :          0 :         data->args.osa_src_fh = NFS_FH(file_inode(dst));
     445                 :          0 :         memcpy(&data->args.osa_stateid, stateid,
     446                 :            :                 sizeof(data->args.osa_stateid));
     447                 :          0 :         msg.rpc_argp = &data->args;
     448                 :          0 :         msg.rpc_resp = &data->res;
     449                 :          0 :         task_setup_data.callback_data = data;
     450                 :          0 :         nfs4_init_sequence(&data->args.osa_seq_args, &data->res.osr_seq_res,
     451                 :            :                            1, 0);
     452                 :          0 :         task = rpc_run_task(&task_setup_data);
     453                 :          0 :         if (IS_ERR(task))
     454                 :          0 :                 return PTR_ERR(task);
     455                 :            :         status = rpc_wait_for_completion_task(task);
     456                 :          0 :         if (status == -ENOTSUPP)
     457                 :          0 :                 dst_server->caps &= ~NFS_CAP_OFFLOAD_CANCEL;
     458                 :          0 :         rpc_put_task(task);
     459                 :          0 :         return status;
     460                 :            : }
     461                 :            : 
     462                 :          0 : static loff_t _nfs42_proc_llseek(struct file *filep,
     463                 :            :                 struct nfs_lock_context *lock, loff_t offset, int whence)
     464                 :            : {
     465                 :            :         struct inode *inode = file_inode(filep);
     466                 :          0 :         struct nfs42_seek_args args = {
     467                 :            :                 .sa_fh          = NFS_FH(inode),
     468                 :            :                 .sa_offset      = offset,
     469                 :            :                 .sa_what        = (whence == SEEK_HOLE) ?
     470                 :          0 :                                         NFS4_CONTENT_HOLE : NFS4_CONTENT_DATA,
     471                 :            :         };
     472                 :            :         struct nfs42_seek_res res;
     473                 :          0 :         struct rpc_message msg = {
     474                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEEK],
     475                 :            :                 .rpc_argp = &args,
     476                 :            :                 .rpc_resp = &res,
     477                 :            :         };
     478                 :            :         struct nfs_server *server = NFS_SERVER(inode);
     479                 :            :         int status;
     480                 :            : 
     481                 :          0 :         if (!nfs_server_capable(inode, NFS_CAP_SEEK))
     482                 :            :                 return -ENOTSUPP;
     483                 :            : 
     484                 :          0 :         status = nfs4_set_rw_stateid(&args.sa_stateid, lock->open_context,
     485                 :            :                         lock, FMODE_READ);
     486                 :          0 :         if (status)
     487                 :          0 :                 return status;
     488                 :            : 
     489                 :          0 :         status = nfs_filemap_write_and_wait_range(inode->i_mapping,
     490                 :            :                         offset, LLONG_MAX);
     491                 :          0 :         if (status)
     492                 :          0 :                 return status;
     493                 :            : 
     494                 :          0 :         status = nfs4_call_sync(server->client, server, &msg,
     495                 :            :                                 &args.seq_args, &res.seq_res, 0);
     496                 :          0 :         if (status == -ENOTSUPP)
     497                 :          0 :                 server->caps &= ~NFS_CAP_SEEK;
     498                 :          0 :         if (status)
     499                 :          0 :                 return status;
     500                 :            : 
     501                 :          0 :         return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
     502                 :            : }
     503                 :            : 
     504                 :          0 : loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
     505                 :            : {
     506                 :            :         struct nfs_server *server = NFS_SERVER(file_inode(filep));
     507                 :          0 :         struct nfs4_exception exception = { };
     508                 :            :         struct nfs_lock_context *lock;
     509                 :            :         loff_t err;
     510                 :            : 
     511                 :          0 :         lock = nfs_get_lock_context(nfs_file_open_context(filep));
     512                 :          0 :         if (IS_ERR(lock))
     513                 :          0 :                 return PTR_ERR(lock);
     514                 :            : 
     515                 :          0 :         exception.inode = file_inode(filep);
     516                 :          0 :         exception.state = lock->open_context->state;
     517                 :            : 
     518                 :            :         do {
     519                 :          0 :                 err = _nfs42_proc_llseek(filep, lock, offset, whence);
     520                 :          0 :                 if (err >= 0)
     521                 :            :                         break;
     522                 :          0 :                 if (err == -ENOTSUPP) {
     523                 :            :                         err = -EOPNOTSUPP;
     524                 :            :                         break;
     525                 :            :                 }
     526                 :          0 :                 err = nfs4_handle_exception(server, err, &exception);
     527                 :          0 :         } while (exception.retry);
     528                 :            : 
     529                 :          0 :         nfs_put_lock_context(lock);
     530                 :          0 :         return err;
     531                 :            : }
     532                 :            : 
     533                 :            : 
     534                 :            : static void
     535                 :          0 : nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata)
     536                 :            : {
     537                 :            :         struct nfs42_layoutstat_data *data = calldata;
     538                 :          0 :         struct inode *inode = data->inode;
     539                 :            :         struct nfs_server *server = NFS_SERVER(inode);
     540                 :            :         struct pnfs_layout_hdr *lo;
     541                 :            : 
     542                 :            :         spin_lock(&inode->i_lock);
     543                 :          0 :         lo = NFS_I(inode)->layout;
     544                 :          0 :         if (!pnfs_layout_is_valid(lo)) {
     545                 :            :                 spin_unlock(&inode->i_lock);
     546                 :          0 :                 rpc_exit(task, 0);
     547                 :          0 :                 return;
     548                 :            :         }
     549                 :            :         nfs4_stateid_copy(&data->args.stateid, &lo->plh_stateid);
     550                 :            :         spin_unlock(&inode->i_lock);
     551                 :          0 :         nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
     552                 :            :                             &data->res.seq_res, task);
     553                 :            : }
     554                 :            : 
     555                 :            : static void
     556                 :          0 : nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
     557                 :            : {
     558                 :            :         struct nfs42_layoutstat_data *data = calldata;
     559                 :          0 :         struct inode *inode = data->inode;
     560                 :            :         struct pnfs_layout_hdr *lo;
     561                 :            : 
     562                 :          0 :         if (!nfs4_sequence_done(task, &data->res.seq_res))
     563                 :          0 :                 return;
     564                 :            : 
     565                 :          0 :         switch (task->tk_status) {
     566                 :            :         case 0:
     567                 :            :                 break;
     568                 :            :         case -NFS4ERR_BADHANDLE:
     569                 :            :         case -ESTALE:
     570                 :          0 :                 pnfs_destroy_layout(NFS_I(inode));
     571                 :          0 :                 break;
     572                 :            :         case -NFS4ERR_EXPIRED:
     573                 :            :         case -NFS4ERR_ADMIN_REVOKED:
     574                 :            :         case -NFS4ERR_DELEG_REVOKED:
     575                 :            :         case -NFS4ERR_STALE_STATEID:
     576                 :            :         case -NFS4ERR_BAD_STATEID:
     577                 :            :                 spin_lock(&inode->i_lock);
     578                 :          0 :                 lo = NFS_I(inode)->layout;
     579                 :          0 :                 if (pnfs_layout_is_valid(lo) &&
     580                 :            :                     nfs4_stateid_match(&data->args.stateid,
     581                 :          0 :                                              &lo->plh_stateid)) {
     582                 :          0 :                         LIST_HEAD(head);
     583                 :            : 
     584                 :            :                         /*
     585                 :            :                          * Mark the bad layout state as invalid, then retry
     586                 :            :                          * with the current stateid.
     587                 :            :                          */
     588                 :          0 :                         pnfs_mark_layout_stateid_invalid(lo, &head);
     589                 :            :                         spin_unlock(&inode->i_lock);
     590                 :          0 :                         pnfs_free_lseg_list(&head);
     591                 :          0 :                         nfs_commit_inode(inode, 0);
     592                 :            :                 } else
     593                 :            :                         spin_unlock(&inode->i_lock);
     594                 :            :                 break;
     595                 :            :         case -NFS4ERR_OLD_STATEID:
     596                 :            :                 spin_lock(&inode->i_lock);
     597                 :          0 :                 lo = NFS_I(inode)->layout;
     598                 :          0 :                 if (pnfs_layout_is_valid(lo) &&
     599                 :            :                     nfs4_stateid_match_other(&data->args.stateid,
     600                 :            :                                         &lo->plh_stateid)) {
     601                 :            :                         /* Do we need to delay before resending? */
     602                 :          0 :                         if (!nfs4_stateid_is_newer(&lo->plh_stateid,
     603                 :            :                                                 &data->args.stateid))
     604                 :          0 :                                 rpc_delay(task, HZ);
     605                 :          0 :                         rpc_restart_call_prepare(task);
     606                 :            :                 }
     607                 :            :                 spin_unlock(&inode->i_lock);
     608                 :            :                 break;
     609                 :            :         case -ENOTSUPP:
     610                 :            :         case -EOPNOTSUPP:
     611                 :          0 :                 NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTSTATS;
     612                 :            :         }
     613                 :            : }
     614                 :            : 
     615                 :            : static void
     616                 :          0 : nfs42_layoutstat_release(void *calldata)
     617                 :            : {
     618                 :            :         struct nfs42_layoutstat_data *data = calldata;
     619                 :          0 :         struct nfs42_layoutstat_devinfo *devinfo = data->args.devinfo;
     620                 :            :         int i;
     621                 :            : 
     622                 :          0 :         for (i = 0; i < data->args.num_dev; i++) {
     623                 :          0 :                 if (devinfo[i].ld_private.ops && devinfo[i].ld_private.ops->free)
     624                 :          0 :                         devinfo[i].ld_private.ops->free(&devinfo[i].ld_private);
     625                 :            :         }
     626                 :            : 
     627                 :          0 :         pnfs_put_layout_hdr(NFS_I(data->args.inode)->layout);
     628                 :          0 :         smp_mb__before_atomic();
     629                 :          0 :         clear_bit(NFS_INO_LAYOUTSTATS, &NFS_I(data->args.inode)->flags);
     630                 :          0 :         smp_mb__after_atomic();
     631                 :          0 :         nfs_iput_and_deactive(data->inode);
     632                 :          0 :         kfree(data->args.devinfo);
     633                 :          0 :         kfree(data);
     634                 :          0 : }
     635                 :            : 
     636                 :            : static const struct rpc_call_ops nfs42_layoutstat_ops = {
     637                 :            :         .rpc_call_prepare = nfs42_layoutstat_prepare,
     638                 :            :         .rpc_call_done = nfs42_layoutstat_done,
     639                 :            :         .rpc_release = nfs42_layoutstat_release,
     640                 :            : };
     641                 :            : 
     642                 :          0 : int nfs42_proc_layoutstats_generic(struct nfs_server *server,
     643                 :            :                                    struct nfs42_layoutstat_data *data)
     644                 :            : {
     645                 :          0 :         struct rpc_message msg = {
     646                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTSTATS],
     647                 :          0 :                 .rpc_argp = &data->args,
     648                 :          0 :                 .rpc_resp = &data->res,
     649                 :            :         };
     650                 :          0 :         struct rpc_task_setup task_setup = {
     651                 :          0 :                 .rpc_client = server->client,
     652                 :            :                 .rpc_message = &msg,
     653                 :            :                 .callback_ops = &nfs42_layoutstat_ops,
     654                 :            :                 .callback_data = data,
     655                 :            :                 .flags = RPC_TASK_ASYNC,
     656                 :            :         };
     657                 :            :         struct rpc_task *task;
     658                 :            : 
     659                 :          0 :         data->inode = nfs_igrab_and_active(data->args.inode);
     660                 :          0 :         if (!data->inode) {
     661                 :          0 :                 nfs42_layoutstat_release(data);
     662                 :          0 :                 return -EAGAIN;
     663                 :            :         }
     664                 :          0 :         nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0, 0);
     665                 :          0 :         task = rpc_run_task(&task_setup);
     666                 :          0 :         if (IS_ERR(task))
     667                 :          0 :                 return PTR_ERR(task);
     668                 :          0 :         rpc_put_task(task);
     669                 :          0 :         return 0;
     670                 :            : }
     671                 :            : 
     672                 :            : static struct nfs42_layouterror_data *
     673                 :          0 : nfs42_alloc_layouterror_data(struct pnfs_layout_segment *lseg, gfp_t gfp_flags)
     674                 :            : {
     675                 :            :         struct nfs42_layouterror_data *data;
     676                 :          0 :         struct inode *inode = lseg->pls_layout->plh_inode;
     677                 :            : 
     678                 :          0 :         data = kzalloc(sizeof(*data), gfp_flags);
     679                 :          0 :         if (data) {
     680                 :          0 :                 data->args.inode = data->inode = nfs_igrab_and_active(inode);
     681                 :          0 :                 if (data->inode) {
     682                 :          0 :                         data->lseg = pnfs_get_lseg(lseg);
     683                 :          0 :                         if (data->lseg)
     684                 :            :                                 return data;
     685                 :          0 :                         nfs_iput_and_deactive(data->inode);
     686                 :            :                 }
     687                 :          0 :                 kfree(data);
     688                 :            :         }
     689                 :            :         return NULL;
     690                 :            : }
     691                 :            : 
     692                 :            : static void
     693                 :          0 : nfs42_free_layouterror_data(struct nfs42_layouterror_data *data)
     694                 :            : {
     695                 :          0 :         pnfs_put_lseg(data->lseg);
     696                 :          0 :         nfs_iput_and_deactive(data->inode);
     697                 :          0 :         kfree(data);
     698                 :          0 : }
     699                 :            : 
     700                 :            : static void
     701                 :          0 : nfs42_layouterror_prepare(struct rpc_task *task, void *calldata)
     702                 :            : {
     703                 :            :         struct nfs42_layouterror_data *data = calldata;
     704                 :          0 :         struct inode *inode = data->inode;
     705                 :            :         struct nfs_server *server = NFS_SERVER(inode);
     706                 :          0 :         struct pnfs_layout_hdr *lo = data->lseg->pls_layout;
     707                 :            :         unsigned i;
     708                 :            : 
     709                 :            :         spin_lock(&inode->i_lock);
     710                 :          0 :         if (!pnfs_layout_is_valid(lo)) {
     711                 :            :                 spin_unlock(&inode->i_lock);
     712                 :          0 :                 rpc_exit(task, 0);
     713                 :          0 :                 return;
     714                 :            :         }
     715                 :          0 :         for (i = 0; i < data->args.num_errors; i++)
     716                 :            :                 nfs4_stateid_copy(&data->args.errors[i].stateid,
     717                 :            :                                 &lo->plh_stateid);
     718                 :            :         spin_unlock(&inode->i_lock);
     719                 :          0 :         nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
     720                 :            :                             &data->res.seq_res, task);
     721                 :            : }
     722                 :            : 
     723                 :            : static void
     724                 :          0 : nfs42_layouterror_done(struct rpc_task *task, void *calldata)
     725                 :            : {
     726                 :            :         struct nfs42_layouterror_data *data = calldata;
     727                 :          0 :         struct inode *inode = data->inode;
     728                 :          0 :         struct pnfs_layout_hdr *lo = data->lseg->pls_layout;
     729                 :            : 
     730                 :          0 :         if (!nfs4_sequence_done(task, &data->res.seq_res))
     731                 :          0 :                 return;
     732                 :            : 
     733                 :          0 :         switch (task->tk_status) {
     734                 :            :         case 0:
     735                 :            :                 break;
     736                 :            :         case -NFS4ERR_BADHANDLE:
     737                 :            :         case -ESTALE:
     738                 :          0 :                 pnfs_destroy_layout(NFS_I(inode));
     739                 :          0 :                 break;
     740                 :            :         case -NFS4ERR_EXPIRED:
     741                 :            :         case -NFS4ERR_ADMIN_REVOKED:
     742                 :            :         case -NFS4ERR_DELEG_REVOKED:
     743                 :            :         case -NFS4ERR_STALE_STATEID:
     744                 :            :         case -NFS4ERR_BAD_STATEID:
     745                 :            :                 spin_lock(&inode->i_lock);
     746                 :          0 :                 if (pnfs_layout_is_valid(lo) &&
     747                 :            :                     nfs4_stateid_match(&data->args.errors[0].stateid,
     748                 :          0 :                                              &lo->plh_stateid)) {
     749                 :          0 :                         LIST_HEAD(head);
     750                 :            : 
     751                 :            :                         /*
     752                 :            :                          * Mark the bad layout state as invalid, then retry
     753                 :            :                          * with the current stateid.
     754                 :            :                          */
     755                 :          0 :                         pnfs_mark_layout_stateid_invalid(lo, &head);
     756                 :            :                         spin_unlock(&inode->i_lock);
     757                 :          0 :                         pnfs_free_lseg_list(&head);
     758                 :          0 :                         nfs_commit_inode(inode, 0);
     759                 :            :                 } else
     760                 :            :                         spin_unlock(&inode->i_lock);
     761                 :            :                 break;
     762                 :            :         case -NFS4ERR_OLD_STATEID:
     763                 :            :                 spin_lock(&inode->i_lock);
     764                 :          0 :                 if (pnfs_layout_is_valid(lo) &&
     765                 :            :                     nfs4_stateid_match_other(&data->args.errors[0].stateid,
     766                 :            :                                         &lo->plh_stateid)) {
     767                 :            :                         /* Do we need to delay before resending? */
     768                 :          0 :                         if (!nfs4_stateid_is_newer(&lo->plh_stateid,
     769                 :            :                                                 &data->args.errors[0].stateid))
     770                 :          0 :                                 rpc_delay(task, HZ);
     771                 :          0 :                         rpc_restart_call_prepare(task);
     772                 :            :                 }
     773                 :            :                 spin_unlock(&inode->i_lock);
     774                 :            :                 break;
     775                 :            :         case -ENOTSUPP:
     776                 :            :         case -EOPNOTSUPP:
     777                 :          0 :                 NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTERROR;
     778                 :            :         }
     779                 :            : }
     780                 :            : 
     781                 :            : static void
     782                 :          0 : nfs42_layouterror_release(void *calldata)
     783                 :            : {
     784                 :            :         struct nfs42_layouterror_data *data = calldata;
     785                 :            : 
     786                 :          0 :         nfs42_free_layouterror_data(data);
     787                 :          0 : }
     788                 :            : 
     789                 :            : static const struct rpc_call_ops nfs42_layouterror_ops = {
     790                 :            :         .rpc_call_prepare = nfs42_layouterror_prepare,
     791                 :            :         .rpc_call_done = nfs42_layouterror_done,
     792                 :            :         .rpc_release = nfs42_layouterror_release,
     793                 :            : };
     794                 :            : 
     795                 :          0 : int nfs42_proc_layouterror(struct pnfs_layout_segment *lseg,
     796                 :            :                 const struct nfs42_layout_error *errors, size_t n)
     797                 :            : {
     798                 :          0 :         struct inode *inode = lseg->pls_layout->plh_inode;
     799                 :            :         struct nfs42_layouterror_data *data;
     800                 :            :         struct rpc_task *task;
     801                 :          0 :         struct rpc_message msg = {
     802                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTERROR],
     803                 :            :         };
     804                 :          0 :         struct rpc_task_setup task_setup = {
     805                 :            :                 .rpc_message = &msg,
     806                 :            :                 .callback_ops = &nfs42_layouterror_ops,
     807                 :            :                 .flags = RPC_TASK_ASYNC,
     808                 :            :         };
     809                 :            :         unsigned int i;
     810                 :            : 
     811                 :          0 :         if (!nfs_server_capable(inode, NFS_CAP_LAYOUTERROR))
     812                 :            :                 return -EOPNOTSUPP;
     813                 :          0 :         if (n > NFS42_LAYOUTERROR_MAX)
     814                 :            :                 return -EINVAL;
     815                 :          0 :         data = nfs42_alloc_layouterror_data(lseg, GFP_NOFS);
     816                 :          0 :         if (!data)
     817                 :            :                 return -ENOMEM;
     818                 :          0 :         for (i = 0; i < n; i++) {
     819                 :          0 :                 data->args.errors[i] = errors[i];
     820                 :          0 :                 data->args.num_errors++;
     821                 :          0 :                 data->res.num_errors++;
     822                 :            :         }
     823                 :          0 :         msg.rpc_argp = &data->args;
     824                 :          0 :         msg.rpc_resp = &data->res;
     825                 :          0 :         task_setup.callback_data = data;
     826                 :          0 :         task_setup.rpc_client = NFS_SERVER(inode)->client;
     827                 :          0 :         nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0, 0);
     828                 :          0 :         task = rpc_run_task(&task_setup);
     829                 :          0 :         if (IS_ERR(task))
     830                 :          0 :                 return PTR_ERR(task);
     831                 :          0 :         rpc_put_task(task);
     832                 :          0 :         return 0;
     833                 :            : }
     834                 :            : EXPORT_SYMBOL_GPL(nfs42_proc_layouterror);
     835                 :            : 
     836                 :          0 : static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
     837                 :            :                 struct file *dst_f, struct nfs_lock_context *src_lock,
     838                 :            :                 struct nfs_lock_context *dst_lock, loff_t src_offset,
     839                 :            :                 loff_t dst_offset, loff_t count)
     840                 :            : {
     841                 :            :         struct inode *src_inode = file_inode(src_f);
     842                 :            :         struct inode *dst_inode = file_inode(dst_f);
     843                 :            :         struct nfs_server *server = NFS_SERVER(dst_inode);
     844                 :          0 :         struct nfs42_clone_args args = {
     845                 :            :                 .src_fh = NFS_FH(src_inode),
     846                 :            :                 .dst_fh = NFS_FH(dst_inode),
     847                 :            :                 .src_offset = src_offset,
     848                 :            :                 .dst_offset = dst_offset,
     849                 :            :                 .count = count,
     850                 :          0 :                 .dst_bitmask = server->cache_consistency_bitmask,
     851                 :            :         };
     852                 :          0 :         struct nfs42_clone_res res = {
     853                 :            :                 .server = server,
     854                 :            :         };
     855                 :            :         int status;
     856                 :            : 
     857                 :          0 :         msg->rpc_argp = &args;
     858                 :          0 :         msg->rpc_resp = &res;
     859                 :            : 
     860                 :          0 :         status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context,
     861                 :            :                         src_lock, FMODE_READ);
     862                 :          0 :         if (status)
     863                 :            :                 return status;
     864                 :            : 
     865                 :          0 :         status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context,
     866                 :            :                         dst_lock, FMODE_WRITE);
     867                 :          0 :         if (status)
     868                 :            :                 return status;
     869                 :            : 
     870                 :          0 :         res.dst_fattr = nfs_alloc_fattr();
     871                 :          0 :         if (!res.dst_fattr)
     872                 :            :                 return -ENOMEM;
     873                 :            : 
     874                 :          0 :         status = nfs4_call_sync(server->client, server, msg,
     875                 :            :                                 &args.seq_args, &res.seq_res, 0);
     876                 :          0 :         if (status == 0)
     877                 :          0 :                 status = nfs_post_op_update_inode(dst_inode, res.dst_fattr);
     878                 :            : 
     879                 :          0 :         kfree(res.dst_fattr);
     880                 :          0 :         return status;
     881                 :            : }
     882                 :            : 
     883                 :          0 : int nfs42_proc_clone(struct file *src_f, struct file *dst_f,
     884                 :            :                      loff_t src_offset, loff_t dst_offset, loff_t count)
     885                 :            : {
     886                 :          0 :         struct rpc_message msg = {
     887                 :            :                 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLONE],
     888                 :            :         };
     889                 :            :         struct inode *inode = file_inode(src_f);
     890                 :            :         struct nfs_server *server = NFS_SERVER(file_inode(src_f));
     891                 :            :         struct nfs_lock_context *src_lock;
     892                 :            :         struct nfs_lock_context *dst_lock;
     893                 :          0 :         struct nfs4_exception src_exception = { };
     894                 :          0 :         struct nfs4_exception dst_exception = { };
     895                 :            :         int err, err2;
     896                 :            : 
     897                 :          0 :         if (!nfs_server_capable(inode, NFS_CAP_CLONE))
     898                 :            :                 return -EOPNOTSUPP;
     899                 :            : 
     900                 :          0 :         src_lock = nfs_get_lock_context(nfs_file_open_context(src_f));
     901                 :          0 :         if (IS_ERR(src_lock))
     902                 :          0 :                 return PTR_ERR(src_lock);
     903                 :            : 
     904                 :          0 :         src_exception.inode = file_inode(src_f);
     905                 :          0 :         src_exception.state = src_lock->open_context->state;
     906                 :            : 
     907                 :          0 :         dst_lock = nfs_get_lock_context(nfs_file_open_context(dst_f));
     908                 :          0 :         if (IS_ERR(dst_lock)) {
     909                 :            :                 err = PTR_ERR(dst_lock);
     910                 :          0 :                 goto out_put_src_lock;
     911                 :            :         }
     912                 :            : 
     913                 :          0 :         dst_exception.inode = file_inode(dst_f);
     914                 :          0 :         dst_exception.state = dst_lock->open_context->state;
     915                 :            : 
     916                 :            :         do {
     917                 :          0 :                 err = _nfs42_proc_clone(&msg, src_f, dst_f, src_lock, dst_lock,
     918                 :            :                                         src_offset, dst_offset, count);
     919                 :          0 :                 if (err == -ENOTSUPP || err == -EOPNOTSUPP) {
     920                 :          0 :                         NFS_SERVER(inode)->caps &= ~NFS_CAP_CLONE;
     921                 :            :                         err = -EOPNOTSUPP;
     922                 :          0 :                         break;
     923                 :            :                 }
     924                 :            : 
     925                 :          0 :                 err2 = nfs4_handle_exception(server, err, &src_exception);
     926                 :          0 :                 err = nfs4_handle_exception(server, err, &dst_exception);
     927                 :          0 :                 if (!err)
     928                 :            :                         err = err2;
     929                 :          0 :         } while (src_exception.retry || dst_exception.retry);
     930                 :            : 
     931                 :          0 :         nfs_put_lock_context(dst_lock);
     932                 :            : out_put_src_lock:
     933                 :          0 :         nfs_put_lock_context(src_lock);
     934                 :          0 :         return err;
     935                 :            : }
    

Generated by: LCOV version 1.14