Skip to content

Commit 5468fc8

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
NFSv4/pNFS: Do layout state recovery upon reboot
Some pNFS implementations, such as flexible files, want the client to send the layout stats and layout errors that may have incurred while the metadata server was booting. To do so, the client sends a layoutreturn with an all-zero stateid while the server is in grace during reboot recovery. Signed-off-by: Trond Myklebust <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent ad3c436 commit 5468fc8

File tree

5 files changed

+110
-9
lines changed

5 files changed

+110
-9
lines changed

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2548,7 +2548,7 @@ ff_layout_set_layoutdriver(struct nfs_server *server,
25482548
const struct nfs_fh *dummy)
25492549
{
25502550
#if IS_ENABLED(CONFIG_NFS_V4_2)
2551-
server->caps |= NFS_CAP_LAYOUTSTATS;
2551+
server->caps |= NFS_CAP_LAYOUTSTATS | NFS_CAP_REBOOT_LAYOUTRETURN;
25522552
#endif
25532553
return 0;
25542554
}

fs/nfs/nfs4state.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,7 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
18631863

18641864
if (!nfs4_state_clear_reclaim_reboot(clp))
18651865
return;
1866+
pnfs_destroy_all_layouts(clp);
18661867
ops = clp->cl_mvops->reboot_recovery_ops;
18671868
cred = nfs4_get_clid_cred(clp);
18681869
err = nfs4_reclaim_complete(clp, ops, cred);
@@ -2068,7 +2069,6 @@ static int nfs4_establish_lease(struct nfs_client *clp)
20682069
put_cred(cred);
20692070
if (status != 0)
20702071
return status;
2071-
pnfs_destroy_all_layouts(clp);
20722072
return 0;
20732073
}
20742074

@@ -2680,6 +2680,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
26802680
section = "reclaim reboot";
26812681
status = nfs4_do_reclaim(clp,
26822682
clp->cl_mvops->reboot_recovery_ops);
2683+
if (status == 0)
2684+
status = pnfs_layout_handle_reboot(clp);
26832685
if (status == -EAGAIN)
26842686
continue;
26852687
if (status < 0)

fs/nfs/pnfs.c

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ static void pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo,
6161
u32 seq);
6262
static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
6363
struct list_head *tmp_list);
64+
static int pnfs_layout_return_on_reboot(struct pnfs_layout_hdr *lo);
6465

6566
/* Return the registered pnfs layout driver module matching given id */
6667
static struct pnfs_layoutdriver_type *
@@ -937,25 +938,37 @@ int pnfs_layout_destroy_byfsid(struct nfs_client *clp, struct nfs_fsid *fsid,
937938
return pnfs_layout_free_bulk_destroy_list(&layout_list, mode);
938939
}
939940

940-
int pnfs_layout_destroy_byclid(struct nfs_client *clp,
941-
enum pnfs_layout_destroy_mode mode)
941+
static void pnfs_layout_build_destroy_list_byclient(struct nfs_client *clp,
942+
struct list_head *list)
942943
{
943944
struct nfs_server *server;
944-
LIST_HEAD(layout_list);
945945

946946
spin_lock(&clp->cl_lock);
947947
rcu_read_lock();
948948
restart:
949949
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
950-
if (pnfs_layout_bulk_destroy_byserver_locked(clp,
951-
server,
952-
&layout_list) != 0)
950+
if (pnfs_layout_bulk_destroy_byserver_locked(clp, server,
951+
list) != 0)
953952
goto restart;
954953
}
955954
rcu_read_unlock();
956955
spin_unlock(&clp->cl_lock);
956+
}
957957

958-
return pnfs_layout_free_bulk_destroy_list(&layout_list, mode);
958+
static int pnfs_layout_do_destroy_byclid(struct nfs_client *clp,
959+
struct list_head *list,
960+
enum pnfs_layout_destroy_mode mode)
961+
{
962+
pnfs_layout_build_destroy_list_byclient(clp, list);
963+
return pnfs_layout_free_bulk_destroy_list(list, mode);
964+
}
965+
966+
int pnfs_layout_destroy_byclid(struct nfs_client *clp,
967+
enum pnfs_layout_destroy_mode mode)
968+
{
969+
LIST_HEAD(layout_list);
970+
971+
return pnfs_layout_do_destroy_byclid(clp, &layout_list, mode);
959972
}
960973

961974
/*
@@ -971,6 +984,67 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
971984
pnfs_layout_destroy_byclid(clp, PNFS_LAYOUT_INVALIDATE);
972985
}
973986

987+
static void pnfs_layout_build_recover_list_byclient(struct nfs_client *clp,
988+
struct list_head *list)
989+
{
990+
struct nfs_server *server;
991+
992+
spin_lock(&clp->cl_lock);
993+
rcu_read_lock();
994+
restart:
995+
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
996+
if (!(server->caps & NFS_CAP_REBOOT_LAYOUTRETURN))
997+
continue;
998+
if (pnfs_layout_bulk_destroy_byserver_locked(clp, server,
999+
list) != 0)
1000+
goto restart;
1001+
}
1002+
rcu_read_unlock();
1003+
spin_unlock(&clp->cl_lock);
1004+
}
1005+
1006+
static int pnfs_layout_bulk_list_reboot(struct list_head *list)
1007+
{
1008+
struct pnfs_layout_hdr *lo;
1009+
struct nfs_server *server;
1010+
int ret;
1011+
1012+
list_for_each_entry(lo, list, plh_bulk_destroy) {
1013+
server = NFS_SERVER(lo->plh_inode);
1014+
ret = pnfs_layout_return_on_reboot(lo);
1015+
switch (ret) {
1016+
case 0:
1017+
continue;
1018+
case -NFS4ERR_BAD_STATEID:
1019+
server->caps &= ~NFS_CAP_REBOOT_LAYOUTRETURN;
1020+
break;
1021+
case -NFS4ERR_NO_GRACE:
1022+
break;
1023+
default:
1024+
goto err;
1025+
}
1026+
break;
1027+
}
1028+
return 0;
1029+
err:
1030+
return ret;
1031+
}
1032+
1033+
int pnfs_layout_handle_reboot(struct nfs_client *clp)
1034+
{
1035+
LIST_HEAD(list);
1036+
int ret = 0, ret2;
1037+
1038+
pnfs_layout_build_recover_list_byclient(clp, &list);
1039+
if (!list_empty(&list))
1040+
ret = pnfs_layout_bulk_list_reboot(&list);
1041+
ret2 = pnfs_layout_do_destroy_byclid(clp, &list,
1042+
PNFS_LAYOUT_INVALIDATE);
1043+
if (!ret)
1044+
ret = ret2;
1045+
return (ret == 0) ? 0 : -EAGAIN;
1046+
}
1047+
9741048
static void
9751049
pnfs_set_layout_cred(struct pnfs_layout_hdr *lo, const struct cred *cred)
9761050
{
@@ -1445,6 +1519,24 @@ pnfs_commit_and_return_layout(struct inode *inode)
14451519
return ret;
14461520
}
14471521

1522+
static int pnfs_layout_return_on_reboot(struct pnfs_layout_hdr *lo)
1523+
{
1524+
struct inode *inode = lo->plh_inode;
1525+
const struct cred *cred;
1526+
1527+
spin_lock(&inode->i_lock);
1528+
if (!pnfs_layout_is_valid(lo)) {
1529+
spin_unlock(&inode->i_lock);
1530+
return 0;
1531+
}
1532+
cred = get_cred(lo->plh_lc_cred);
1533+
pnfs_get_layout_hdr(lo);
1534+
spin_unlock(&inode->i_lock);
1535+
1536+
return pnfs_send_layoutreturn(lo, &zero_stateid, &cred, IOMODE_ANY,
1537+
PNFS_FL_LAYOUTRETURN_PRIVILEGED);
1538+
}
1539+
14481540
bool pnfs_roc(struct inode *ino,
14491541
struct nfs4_layoutreturn_args *args,
14501542
struct nfs4_layoutreturn_res *res,

fs/nfs/pnfs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
356356
struct pnfs_layout_segment *lseg);
357357
void pnfs_layout_return_unused_byclid(struct nfs_client *clp,
358358
enum pnfs_iomode iomode);
359+
int pnfs_layout_handle_reboot(struct nfs_client *clp);
359360

360361
/* nfs4_deviceid_flags */
361362
enum {
@@ -737,6 +738,11 @@ static inline void pnfs_destroy_layout_final(struct nfs_inode *nfsi)
737738
{
738739
}
739740

741+
static inline int pnfs_layout_handle_reboot(struct nfs_client *clp)
742+
{
743+
return 0;
744+
}
745+
740746
static inline struct pnfs_layout_segment *
741747
pnfs_get_lseg(struct pnfs_layout_segment *lseg)
742748
{

include/linux/nfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ struct nfs_server {
278278
#define NFS_CAP_LGOPEN (1U << 5)
279279
#define NFS_CAP_CASE_INSENSITIVE (1U << 6)
280280
#define NFS_CAP_CASE_PRESERVING (1U << 7)
281+
#define NFS_CAP_REBOOT_LAYOUTRETURN (1U << 8)
281282
#define NFS_CAP_OPEN_XOR (1U << 12)
282283
#define NFS_CAP_DELEGTIME (1U << 13)
283284
#define NFS_CAP_POSIX_LOCK (1U << 14)

0 commit comments

Comments
 (0)