Skip to content

Commit e4648aa

Browse files
olgakorn1amschuma-ntap
authored andcommitted
NFS recover from destination server reboot for copies
Mark the destination state to indicate a server-side copy is happening. On detecting a reboot and recovering open state check if any state is engaged in a server-side copy, if so, find the copy and mark it and then signal the waiting thread. Upon wakeup, if copy was marked then propage EAGAIN to the nfsd_copy_file_range and restart the copy from scratch. Signed-off-by: Olga Kornievskaia <kolga@netapp.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 6b8d84e commit e4648aa

File tree

5 files changed

+41
-5
lines changed

5 files changed

+41
-5
lines changed

fs/nfs/nfs42proc.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ static int handle_async_copy(struct nfs42_copy_res *res,
140140
struct nfs4_copy_state *copy;
141141
int status = NFS4_OK;
142142
bool found_pending = false;
143+
struct nfs_open_context *ctx = nfs_file_open_context(dst);
143144

144145
spin_lock(&server->nfs_client->cl_lock);
145146
list_for_each_entry(copy, &server->nfs_client->pending_cb_stateids,
@@ -163,6 +164,7 @@ static int handle_async_copy(struct nfs42_copy_res *res,
163164
}
164165
memcpy(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
165166
init_completion(&copy->completion);
167+
copy->parent_state = ctx->state;
166168

167169
list_add_tail(&copy->copies, &server->ss_copies);
168170
spin_unlock(&server->nfs_client->cl_lock);
@@ -172,15 +174,20 @@ static int handle_async_copy(struct nfs42_copy_res *res,
172174
list_del_init(&copy->copies);
173175
spin_unlock(&server->nfs_client->cl_lock);
174176
if (status == -ERESTARTSYS) {
175-
nfs42_do_offload_cancel_async(dst, &copy->stateid);
176-
kfree(copy);
177-
return status;
177+
goto out_cancel;
178+
} else if (copy->flags) {
179+
status = -EAGAIN;
180+
goto out_cancel;
178181
}
179182
out:
180183
res->write_res.count = copy->count;
181184
memcpy(&res->write_res.verifier, &copy->verf, sizeof(copy->verf));
182185
status = -copy->error;
183186

187+
kfree(copy);
188+
return status;
189+
out_cancel:
190+
nfs42_do_offload_cancel_async(dst, &copy->stateid);
184191
kfree(copy);
185192
return status;
186193
}
@@ -254,6 +261,9 @@ static ssize_t _nfs42_proc_copy(struct file *src,
254261
if (!res->commit_res.verf)
255262
return -ENOMEM;
256263
}
264+
set_bit(NFS_CLNT_DST_SSC_COPY_STATE,
265+
&dst_lock->open_context->state->flags);
266+
257267
status = nfs4_call_sync(server->client, server, &msg,
258268
&args->seq_args, &res->seq_res, 0);
259269
if (status == -ENOTSUPP)

fs/nfs/nfs4_fs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ enum {
163163
NFS_STATE_RECOVERY_FAILED, /* OPEN stateid state recovery failed */
164164
NFS_STATE_MAY_NOTIFY_LOCK, /* server may CB_NOTIFY_LOCK */
165165
NFS_STATE_CHANGE_WAIT, /* A state changing operation is outstanding */
166+
#ifdef CONFIG_NFS_V4_2
167+
NFS_CLNT_DST_SSC_COPY_STATE, /* dst server open state on client*/
168+
#endif /* CONFIG_NFS_V4_2 */
166169
};
167170

168171
struct nfs4_state {

fs/nfs/nfs4file.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,15 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
133133
struct file *file_out, loff_t pos_out,
134134
size_t count, unsigned int flags)
135135
{
136+
ssize_t ret;
137+
136138
if (file_inode(file_in) == file_inode(file_out))
137139
return -EINVAL;
138-
139-
return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
140+
retry:
141+
ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
142+
if (ret == -EAGAIN)
143+
goto retry;
144+
return ret;
140145
}
141146

142147
static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)

fs/nfs/nfs4state.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,22 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
15891589
}
15901590
clear_bit(NFS_STATE_RECLAIM_NOGRACE,
15911591
&state->flags);
1592+
#ifdef CONFIG_NFS_V4_2
1593+
if (test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags)) {
1594+
struct nfs4_copy_state *copy;
1595+
1596+
spin_lock(&sp->so_server->nfs_client->cl_lock);
1597+
list_for_each_entry(copy, &sp->so_server->ss_copies, copies) {
1598+
if (memcmp(&state->stateid.other, &copy->parent_state->stateid.other, NFS4_STATEID_SIZE))
1599+
continue;
1600+
copy->flags = 1;
1601+
complete(&copy->completion);
1602+
printk("AGLO: server rebooted waking up the copy\n");
1603+
break;
1604+
}
1605+
spin_unlock(&sp->so_server->nfs_client->cl_lock);
1606+
}
1607+
#endif /* CONFIG_NFS_V4_2 */
15921608
nfs4_put_open_state(state);
15931609
spin_lock(&sp->so_lock);
15941610
goto restart;

include/linux/nfs_fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ struct nfs4_copy_state {
192192
uint64_t count;
193193
struct nfs_writeverf verf;
194194
int error;
195+
int flags;
196+
struct nfs4_state *parent_state;
195197
};
196198

197199
/*

0 commit comments

Comments
 (0)