diff options
author | Fred Isaman <fred.isaman@gmail.com> | 2016-10-06 12:11:21 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2018-05-31 15:03:11 -0400 |
commit | 2409a976a2990ee1712c0945a75d75eeb3c60c08 (patch) | |
tree | 390eeba3931c247b5716a4ab4fafd52ab77bfc3a | |
parent | 5e36e2a9411210b1f81982af02504cd20f5c91d5 (diff) |
pnfs: Add LAYOUTGET to OPEN of a new file
This triggers when have no pre-existing inode to attach to.
The preexisting case is saved for later.
Signed-off-by: Fred Isaman <fred.isaman@gmail.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r-- | fs/nfs/nfs4proc.c | 21 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 8 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 81 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 17 |
4 files changed, 121 insertions, 6 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c7f982cdcbdd..062a9c753b7e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -86,6 +86,7 @@ | |||
86 | | ATTR_MTIME_SET) | 86 | | ATTR_MTIME_SET) |
87 | 87 | ||
88 | struct nfs4_opendata; | 88 | struct nfs4_opendata; |
89 | static void nfs4_layoutget_release(void *calldata); | ||
89 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 90 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
90 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 91 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
91 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 92 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
@@ -877,6 +878,10 @@ nfs4_sequence_process_interrupted(struct nfs_client *client, | |||
877 | 878 | ||
878 | #else /* !CONFIG_NFS_V4_1 */ | 879 | #else /* !CONFIG_NFS_V4_1 */ |
879 | 880 | ||
881 | static void nfs4_layoutget_release(void *calldata) | ||
882 | { | ||
883 | } | ||
884 | |||
880 | static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) | 885 | static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) |
881 | { | 886 | { |
882 | return nfs40_sequence_done(task, res); | 887 | return nfs40_sequence_done(task, res); |
@@ -1244,6 +1249,8 @@ static void nfs4_opendata_free(struct kref *kref) | |||
1244 | struct nfs4_opendata, kref); | 1249 | struct nfs4_opendata, kref); |
1245 | struct super_block *sb = p->dentry->d_sb; | 1250 | struct super_block *sb = p->dentry->d_sb; |
1246 | 1251 | ||
1252 | if (p->lgp) | ||
1253 | nfs4_layoutget_release(p->lgp); | ||
1247 | nfs_free_seqid(p->o_arg.seqid); | 1254 | nfs_free_seqid(p->o_arg.seqid); |
1248 | nfs4_sequence_free_slot(&p->o_res.seq_res); | 1255 | nfs4_sequence_free_slot(&p->o_res.seq_res); |
1249 | if (p->state != NULL) | 1256 | if (p->state != NULL) |
@@ -2334,8 +2341,10 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, | |||
2334 | if (!ctx) { | 2341 | if (!ctx) { |
2335 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1); | 2342 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1); |
2336 | data->is_recover = true; | 2343 | data->is_recover = true; |
2337 | } else | 2344 | } else { |
2338 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0); | 2345 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0); |
2346 | pnfs_lgopen_prepare(data, ctx); | ||
2347 | } | ||
2339 | task = rpc_run_task(&task_setup_data); | 2348 | task = rpc_run_task(&task_setup_data); |
2340 | if (IS_ERR(task)) | 2349 | if (IS_ERR(task)) |
2341 | return PTR_ERR(task); | 2350 | return PTR_ERR(task); |
@@ -2815,7 +2824,10 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2815 | nfs_inode_attach_open_context(ctx); | 2824 | nfs_inode_attach_open_context(ctx); |
2816 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) | 2825 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) |
2817 | nfs4_schedule_stateid_recovery(server, state); | 2826 | nfs4_schedule_stateid_recovery(server, state); |
2827 | else | ||
2828 | pnfs_parse_lgopen(state->inode, opendata->lgp, ctx); | ||
2818 | } | 2829 | } |
2830 | |||
2819 | out: | 2831 | out: |
2820 | return ret; | 2832 | return ret; |
2821 | } | 2833 | } |
@@ -8722,13 +8734,14 @@ static void nfs4_layoutget_release(void *calldata) | |||
8722 | { | 8734 | { |
8723 | struct nfs4_layoutget *lgp = calldata; | 8735 | struct nfs4_layoutget *lgp = calldata; |
8724 | struct inode *inode = lgp->args.inode; | 8736 | struct inode *inode = lgp->args.inode; |
8725 | struct nfs_server *server = NFS_SERVER(inode); | 8737 | size_t max_pages = lgp->args.layout.pglen / PAGE_SIZE; |
8726 | size_t max_pages = max_response_pages(server); | ||
8727 | 8738 | ||
8728 | dprintk("--> %s\n", __func__); | 8739 | dprintk("--> %s\n", __func__); |
8729 | nfs4_sequence_free_slot(&lgp->res.seq_res); | 8740 | nfs4_sequence_free_slot(&lgp->res.seq_res); |
8730 | nfs4_free_pages(lgp->args.layout.pages, max_pages); | 8741 | nfs4_free_pages(lgp->args.layout.pages, max_pages); |
8731 | pnfs_put_layout_hdr(NFS_I(inode)->layout); | 8742 | if (inode) |
8743 | pnfs_put_layout_hdr(NFS_I(inode)->layout); | ||
8744 | put_rpccred(lgp->cred); | ||
8732 | put_nfs_open_context(lgp->args.ctx); | 8745 | put_nfs_open_context(lgp->args.ctx); |
8733 | kfree(calldata); | 8746 | kfree(calldata); |
8734 | dprintk("<-- %s\n", __func__); | 8747 | dprintk("<-- %s\n", __func__); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index c10a422efe6f..2bf2eaa08ca7 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -77,6 +77,14 @@ const nfs4_stateid invalid_stateid = { | |||
77 | .type = NFS4_INVALID_STATEID_TYPE, | 77 | .type = NFS4_INVALID_STATEID_TYPE, |
78 | }; | 78 | }; |
79 | 79 | ||
80 | const nfs4_stateid current_stateid = { | ||
81 | { | ||
82 | /* Funky initialiser keeps older gcc versions happy */ | ||
83 | .data = { 0x0, 0x0, 0x0, 0x1, 0 }, | ||
84 | }, | ||
85 | .type = NFS4_SPECIAL_STATEID_TYPE, | ||
86 | }; | ||
87 | |||
80 | static DEFINE_MUTEX(nfs_clid_init_mutex); | 88 | static DEFINE_MUTEX(nfs_clid_init_mutex); |
81 | 89 | ||
82 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 90 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 07f1bbd9100c..a0a2484c3aed 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -934,7 +934,7 @@ pnfs_find_server(struct inode *inode, struct nfs_open_context *ctx) | |||
934 | static struct nfs4_layoutget * | 934 | static struct nfs4_layoutget * |
935 | pnfs_alloc_init_layoutget_args(struct inode *ino, | 935 | pnfs_alloc_init_layoutget_args(struct inode *ino, |
936 | struct nfs_open_context *ctx, | 936 | struct nfs_open_context *ctx, |
937 | nfs4_stateid *stateid, | 937 | const nfs4_stateid *stateid, |
938 | const struct pnfs_layout_range *range, | 938 | const struct pnfs_layout_range *range, |
939 | gfp_t gfp_flags) | 939 | gfp_t gfp_flags) |
940 | { | 940 | { |
@@ -978,7 +978,7 @@ pnfs_alloc_init_layoutget_args(struct inode *ino, | |||
978 | lgp->args.ctx = get_nfs_open_context(ctx); | 978 | lgp->args.ctx = get_nfs_open_context(ctx); |
979 | nfs4_stateid_copy(&lgp->args.stateid, stateid); | 979 | nfs4_stateid_copy(&lgp->args.stateid, stateid); |
980 | lgp->gfp_flags = gfp_flags; | 980 | lgp->gfp_flags = gfp_flags; |
981 | lgp->cred = ctx->cred; | 981 | lgp->cred = get_rpccred(ctx->cred); |
982 | return lgp; | 982 | return lgp; |
983 | } | 983 | } |
984 | 984 | ||
@@ -1943,6 +1943,83 @@ pnfs_sanity_check_layout_range(struct pnfs_layout_range *range) | |||
1943 | return true; | 1943 | return true; |
1944 | } | 1944 | } |
1945 | 1945 | ||
1946 | extern const nfs4_stateid current_stateid; | ||
1947 | |||
1948 | static void _lgopen_prepare_attached(struct nfs4_opendata *data, | ||
1949 | struct nfs_open_context *ctx) | ||
1950 | { | ||
1951 | /* STUB */ | ||
1952 | } | ||
1953 | |||
1954 | static void _lgopen_prepare_floating(struct nfs4_opendata *data, | ||
1955 | struct nfs_open_context *ctx) | ||
1956 | { | ||
1957 | struct pnfs_layout_range rng = { | ||
1958 | .iomode = (data->o_arg.fmode & FMODE_WRITE) ? | ||
1959 | IOMODE_RW: IOMODE_READ, | ||
1960 | .offset = 0, | ||
1961 | .length = NFS4_MAX_UINT64, | ||
1962 | }; | ||
1963 | struct nfs4_layoutget *lgp; | ||
1964 | |||
1965 | lgp = pnfs_alloc_init_layoutget_args(NULL, ctx, ¤t_stateid, | ||
1966 | &rng, GFP_KERNEL); | ||
1967 | if (!lgp) | ||
1968 | return; | ||
1969 | data->lgp = lgp; | ||
1970 | data->o_arg.lg_args = &lgp->args; | ||
1971 | data->o_res.lg_res = &lgp->res; | ||
1972 | } | ||
1973 | |||
1974 | void pnfs_lgopen_prepare(struct nfs4_opendata *data, | ||
1975 | struct nfs_open_context *ctx) | ||
1976 | { | ||
1977 | struct nfs_server *server = NFS_SERVER(data->dir->d_inode); | ||
1978 | |||
1979 | if (!(pnfs_enabled_sb(server) && | ||
1980 | server->pnfs_curr_ld->flags & PNFS_LAYOUTGET_ON_OPEN)) | ||
1981 | return; | ||
1982 | /* Could check on max_ops, but currently hardcoded high enough */ | ||
1983 | if (data->state) | ||
1984 | _lgopen_prepare_attached(data, ctx); | ||
1985 | else | ||
1986 | _lgopen_prepare_floating(data, ctx); | ||
1987 | } | ||
1988 | |||
1989 | void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp, | ||
1990 | struct nfs_open_context *ctx) | ||
1991 | { | ||
1992 | struct pnfs_layout_hdr *lo; | ||
1993 | struct pnfs_layout_segment *lseg; | ||
1994 | u32 iomode; | ||
1995 | |||
1996 | if (!lgp || lgp->res.layoutp->len == 0) | ||
1997 | return; | ||
1998 | if (!lgp->args.inode) { | ||
1999 | /* Need to grab lo */ | ||
2000 | spin_lock(&ino->i_lock); | ||
2001 | lo = pnfs_find_alloc_layout(ino, ctx, GFP_KERNEL); | ||
2002 | atomic_inc(&lo->plh_outstanding); | ||
2003 | spin_unlock(&ino->i_lock); | ||
2004 | lgp->args.inode = ino; | ||
2005 | } else | ||
2006 | lo = NFS_I(lgp->args.inode)->layout; | ||
2007 | pnfs_get_layout_hdr(lo); | ||
2008 | |||
2009 | lseg = pnfs_layout_process(lgp); | ||
2010 | atomic_dec(&lo->plh_outstanding); | ||
2011 | if (IS_ERR(lseg)) { | ||
2012 | /* ignore lseg, but would like to mark not to try lgopen */ | ||
2013 | /* clear some lo flags - first and fail ???? */ | ||
2014 | } else { | ||
2015 | iomode = lgp->args.range.iomode; | ||
2016 | pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); | ||
2017 | pnfs_put_lseg(lseg); | ||
2018 | } | ||
2019 | pnfs_clear_first_layoutget(lo); | ||
2020 | pnfs_put_layout_hdr(lo); | ||
2021 | } | ||
2022 | |||
1946 | struct pnfs_layout_segment * | 2023 | struct pnfs_layout_segment * |
1947 | pnfs_layout_process(struct nfs4_layoutget *lgp) | 2024 | pnfs_layout_process(struct nfs4_layoutget *lgp) |
1948 | { | 2025 | { |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 964a7227ea97..b110c09ea89c 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/nfs_page.h> | 35 | #include <linux/nfs_page.h> |
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | 37 | ||
38 | struct nfs4_opendata; | ||
39 | |||
38 | enum { | 40 | enum { |
39 | NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ | 41 | NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ |
40 | NFS_LSEG_ROC, /* roc bit received from server */ | 42 | NFS_LSEG_ROC, /* roc bit received from server */ |
@@ -378,6 +380,10 @@ void pnfs_layout_mark_request_commit(struct nfs_page *req, | |||
378 | struct pnfs_layout_segment *lseg, | 380 | struct pnfs_layout_segment *lseg, |
379 | struct nfs_commit_info *cinfo, | 381 | struct nfs_commit_info *cinfo, |
380 | u32 ds_commit_idx); | 382 | u32 ds_commit_idx); |
383 | void pnfs_lgopen_prepare(struct nfs4_opendata *data, | ||
384 | struct nfs_open_context *ctx); | ||
385 | void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp, | ||
386 | struct nfs_open_context *ctx); | ||
381 | 387 | ||
382 | static inline bool nfs_have_layout(struct inode *inode) | 388 | static inline bool nfs_have_layout(struct inode *inode) |
383 | { | 389 | { |
@@ -778,6 +784,17 @@ static inline bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, | |||
778 | { | 784 | { |
779 | return false; | 785 | return false; |
780 | } | 786 | } |
787 | |||
788 | static inline void pnfs_lgopen_prepare(struct nfs4_opendata *data, | ||
789 | struct nfs_open_context *ctx) | ||
790 | { | ||
791 | } | ||
792 | |||
793 | static inline void pnfs_parse_lgopen(struct inode *ino, | ||
794 | struct nfs4_layoutget *lgp, | ||
795 | struct nfs_open_context *ctx) | ||
796 | { | ||
797 | } | ||
781 | #endif /* CONFIG_NFS_V4_1 */ | 798 | #endif /* CONFIG_NFS_V4_1 */ |
782 | 799 | ||
783 | #if IS_ENABLED(CONFIG_NFS_V4_2) | 800 | #if IS_ENABLED(CONFIG_NFS_V4_2) |