diff options
-rw-r--r-- | fs/nfs/inode.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 38 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 12 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 21 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 |
5 files changed, 69 insertions, 5 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 9ad81ce0c40f..889f7e5e92e1 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -641,6 +641,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f | |||
641 | nfs_init_lock_context(&ctx->lock_context); | 641 | nfs_init_lock_context(&ctx->lock_context); |
642 | ctx->lock_context.open_context = ctx; | 642 | ctx->lock_context.open_context = ctx; |
643 | INIT_LIST_HEAD(&ctx->list); | 643 | INIT_LIST_HEAD(&ctx->list); |
644 | ctx->mdsthreshold = NULL; | ||
644 | return ctx; | 645 | return ctx; |
645 | } | 646 | } |
646 | 647 | ||
@@ -669,6 +670,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
669 | put_rpccred(ctx->cred); | 670 | put_rpccred(ctx->cred); |
670 | dput(ctx->dentry); | 671 | dput(ctx->dentry); |
671 | nfs_sb_deactive(sb); | 672 | nfs_sb_deactive(sb); |
673 | kfree(ctx->mdsthreshold); | ||
672 | kfree(ctx); | 674 | kfree(ctx); |
673 | } | 675 | } |
674 | 676 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8f39bb3ca1b3..e725736ff288 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1782,7 +1782,14 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct | |||
1782 | /* | 1782 | /* |
1783 | * Returns a referenced nfs4_state | 1783 | * Returns a referenced nfs4_state |
1784 | */ | 1784 | */ |
1785 | static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res) | 1785 | static int _nfs4_do_open(struct inode *dir, |
1786 | struct dentry *dentry, | ||
1787 | fmode_t fmode, | ||
1788 | int flags, | ||
1789 | struct iattr *sattr, | ||
1790 | struct rpc_cred *cred, | ||
1791 | struct nfs4_state **res, | ||
1792 | struct nfs4_threshold **ctx_th) | ||
1786 | { | 1793 | { |
1787 | struct nfs4_state_owner *sp; | 1794 | struct nfs4_state_owner *sp; |
1788 | struct nfs4_state *state = NULL; | 1795 | struct nfs4_state *state = NULL; |
@@ -1807,6 +1814,11 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode | |||
1807 | if (opendata == NULL) | 1814 | if (opendata == NULL) |
1808 | goto err_put_state_owner; | 1815 | goto err_put_state_owner; |
1809 | 1816 | ||
1817 | if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { | ||
1818 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); | ||
1819 | if (!opendata->f_attr.mdsthreshold) | ||
1820 | goto err_opendata_put; | ||
1821 | } | ||
1810 | if (dentry->d_inode != NULL) | 1822 | if (dentry->d_inode != NULL) |
1811 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); | 1823 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); |
1812 | 1824 | ||
@@ -1832,11 +1844,19 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode | |||
1832 | nfs_setattr_update_inode(state->inode, sattr); | 1844 | nfs_setattr_update_inode(state->inode, sattr); |
1833 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 1845 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); |
1834 | } | 1846 | } |
1847 | |||
1848 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) | ||
1849 | *ctx_th = opendata->f_attr.mdsthreshold; | ||
1850 | else | ||
1851 | kfree(opendata->f_attr.mdsthreshold); | ||
1852 | opendata->f_attr.mdsthreshold = NULL; | ||
1853 | |||
1835 | nfs4_opendata_put(opendata); | 1854 | nfs4_opendata_put(opendata); |
1836 | nfs4_put_state_owner(sp); | 1855 | nfs4_put_state_owner(sp); |
1837 | *res = state; | 1856 | *res = state; |
1838 | return 0; | 1857 | return 0; |
1839 | err_opendata_put: | 1858 | err_opendata_put: |
1859 | kfree(opendata->f_attr.mdsthreshold); | ||
1840 | nfs4_opendata_put(opendata); | 1860 | nfs4_opendata_put(opendata); |
1841 | err_put_state_owner: | 1861 | err_put_state_owner: |
1842 | nfs4_put_state_owner(sp); | 1862 | nfs4_put_state_owner(sp); |
@@ -1846,14 +1866,21 @@ out_err: | |||
1846 | } | 1866 | } |
1847 | 1867 | ||
1848 | 1868 | ||
1849 | static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred) | 1869 | static struct nfs4_state *nfs4_do_open(struct inode *dir, |
1870 | struct dentry *dentry, | ||
1871 | fmode_t fmode, | ||
1872 | int flags, | ||
1873 | struct iattr *sattr, | ||
1874 | struct rpc_cred *cred, | ||
1875 | struct nfs4_threshold **ctx_th) | ||
1850 | { | 1876 | { |
1851 | struct nfs4_exception exception = { }; | 1877 | struct nfs4_exception exception = { }; |
1852 | struct nfs4_state *res; | 1878 | struct nfs4_state *res; |
1853 | int status; | 1879 | int status; |
1854 | 1880 | ||
1855 | do { | 1881 | do { |
1856 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, &res); | 1882 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, |
1883 | &res, ctx_th); | ||
1857 | if (status == 0) | 1884 | if (status == 0) |
1858 | break; | 1885 | break; |
1859 | /* NOTE: BAD_SEQID means the server and client disagree about the | 1886 | /* NOTE: BAD_SEQID means the server and client disagree about the |
@@ -2177,7 +2204,8 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags | |||
2177 | struct nfs4_state *state; | 2204 | struct nfs4_state *state; |
2178 | 2205 | ||
2179 | /* Protect against concurrent sillydeletes */ | 2206 | /* Protect against concurrent sillydeletes */ |
2180 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, ctx->cred); | 2207 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, |
2208 | ctx->cred, &ctx->mdsthreshold); | ||
2181 | if (IS_ERR(state)) | 2209 | if (IS_ERR(state)) |
2182 | return ERR_CAST(state); | 2210 | return ERR_CAST(state); |
2183 | ctx->state = state; | 2211 | ctx->state = state; |
@@ -2779,7 +2807,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2779 | fmode = ctx->mode; | 2807 | fmode = ctx->mode; |
2780 | } | 2808 | } |
2781 | sattr->ia_mode &= ~current_umask(); | 2809 | sattr->ia_mode &= ~current_umask(); |
2782 | state = nfs4_do_open(dir, de, fmode, flags, sattr, cred); | 2810 | state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL); |
2783 | d_drop(dentry); | 2811 | d_drop(dentry); |
2784 | if (IS_ERR(state)) { | 2812 | if (IS_ERR(state)) { |
2785 | status = PTR_ERR(state); | 2813 | status = PTR_ERR(state); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 5d09a36b2cd8..cbcb6aea58a3 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1630,3 +1630,15 @@ out_free: | |||
1630 | kfree(data); | 1630 | kfree(data); |
1631 | goto out; | 1631 | goto out; |
1632 | } | 1632 | } |
1633 | |||
1634 | struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | ||
1635 | { | ||
1636 | struct nfs4_threshold *thp; | ||
1637 | |||
1638 | thp = kzalloc(sizeof(*thp), GFP_NOFS); | ||
1639 | if (!thp) { | ||
1640 | dprintk("%s mdsthreshold allocation failed\n", __func__); | ||
1641 | return NULL; | ||
1642 | } | ||
1643 | return thp; | ||
1644 | } | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 7980756b2f57..29fd23c0efdc 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -227,6 +227,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head, | |||
227 | const struct nfs_pgio_completion_ops *compl_ops); | 227 | const struct nfs_pgio_completion_ops *compl_ops); |
228 | int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head, | 228 | int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head, |
229 | const struct nfs_pgio_completion_ops *compl_ops); | 229 | const struct nfs_pgio_completion_ops *compl_ops); |
230 | struct nfs4_threshold *pnfs_mdsthreshold_alloc(void); | ||
230 | 231 | ||
231 | /* nfs4_deviceid_flags */ | 232 | /* nfs4_deviceid_flags */ |
232 | enum { | 233 | enum { |
@@ -360,6 +361,14 @@ static inline int pnfs_return_layout(struct inode *ino) | |||
360 | return 0; | 361 | return 0; |
361 | } | 362 | } |
362 | 363 | ||
364 | static inline bool | ||
365 | pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, | ||
366 | struct nfs_server *nfss) | ||
367 | { | ||
368 | return (dst && src && src->bm != 0 && | ||
369 | nfss->pnfs_curr_ld->id == src->l_type); | ||
370 | } | ||
371 | |||
363 | #ifdef NFS_DEBUG | 372 | #ifdef NFS_DEBUG |
364 | void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id); | 373 | void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id); |
365 | #else | 374 | #else |
@@ -485,6 +494,18 @@ static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
485 | return 0; | 494 | return 0; |
486 | } | 495 | } |
487 | 496 | ||
497 | static inline bool | ||
498 | pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, | ||
499 | struct nfs_server *nfss) | ||
500 | { | ||
501 | return false; | ||
502 | } | ||
503 | |||
504 | static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | ||
505 | { | ||
506 | return NULL; | ||
507 | } | ||
508 | |||
488 | #endif /* CONFIG_NFS_V4_1 */ | 509 | #endif /* CONFIG_NFS_V4_1 */ |
489 | 510 | ||
490 | #endif /* FS_NFS_PNFS_H */ | 511 | #endif /* FS_NFS_PNFS_H */ |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 80a9385b88ab..ce910cb7d761 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -102,6 +102,7 @@ struct nfs_open_context { | |||
102 | int error; | 102 | int error; |
103 | 103 | ||
104 | struct list_head list; | 104 | struct list_head list; |
105 | struct nfs4_threshold *mdsthreshold; | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | struct nfs_open_dir_context { | 108 | struct nfs_open_dir_context { |