diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 149 |
1 files changed, 119 insertions, 30 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c1c7a9d78722..941246f2b43d 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include "iostat.h" | 48 | #include "iostat.h" |
49 | #include "internal.h" | 49 | #include "internal.h" |
50 | #include "fscache.h" | 50 | #include "fscache.h" |
51 | #include "dns_resolve.h" | ||
52 | #include "pnfs.h" | 51 | #include "pnfs.h" |
53 | #include "nfs.h" | 52 | #include "nfs.h" |
54 | #include "netns.h" | 53 | #include "netns.h" |
@@ -79,7 +78,7 @@ int nfs_wait_bit_killable(void *word) | |||
79 | { | 78 | { |
80 | if (fatal_signal_pending(current)) | 79 | if (fatal_signal_pending(current)) |
81 | return -ERESTARTSYS; | 80 | return -ERESTARTSYS; |
82 | freezable_schedule(); | 81 | freezable_schedule_unsafe(); |
83 | return 0; | 82 | return 0; |
84 | } | 83 | } |
85 | EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); | 84 | EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); |
@@ -162,11 +161,19 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
162 | 161 | ||
163 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); | 162 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); |
164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 163 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
165 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | ||
166 | nfs_fscache_invalidate(inode); | 164 | nfs_fscache_invalidate(inode); |
167 | } else { | 165 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
168 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 166 | | NFS_INO_INVALID_LABEL |
169 | } | 167 | | NFS_INO_INVALID_DATA |
168 | | NFS_INO_INVALID_ACCESS | ||
169 | | NFS_INO_INVALID_ACL | ||
170 | | NFS_INO_REVAL_PAGECACHE; | ||
171 | } else | ||
172 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | ||
173 | | NFS_INO_INVALID_LABEL | ||
174 | | NFS_INO_INVALID_ACCESS | ||
175 | | NFS_INO_INVALID_ACL | ||
176 | | NFS_INO_REVAL_PAGECACHE; | ||
170 | } | 177 | } |
171 | 178 | ||
172 | void nfs_zap_caches(struct inode *inode) | 179 | void nfs_zap_caches(struct inode *inode) |
@@ -257,12 +264,72 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
257 | return 0; | 264 | return 0; |
258 | } | 265 | } |
259 | 266 | ||
267 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
268 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
269 | struct nfs4_label *label) | ||
270 | { | ||
271 | int error; | ||
272 | |||
273 | if (label == NULL) | ||
274 | return; | ||
275 | |||
276 | if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL) == 0) | ||
277 | return; | ||
278 | |||
279 | if (NFS_SERVER(inode)->nfs_client->cl_minorversion < 2) | ||
280 | return; | ||
281 | |||
282 | if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) { | ||
283 | error = security_inode_notifysecctx(inode, label->label, | ||
284 | label->len); | ||
285 | if (error) | ||
286 | printk(KERN_ERR "%s() %s %d " | ||
287 | "security_inode_notifysecctx() %d\n", | ||
288 | __func__, | ||
289 | (char *)label->label, | ||
290 | label->len, error); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) | ||
295 | { | ||
296 | struct nfs4_label *label = NULL; | ||
297 | int minor_version = server->nfs_client->cl_minorversion; | ||
298 | |||
299 | if (minor_version < 2) | ||
300 | return label; | ||
301 | |||
302 | if (!(server->caps & NFS_CAP_SECURITY_LABEL)) | ||
303 | return label; | ||
304 | |||
305 | label = kzalloc(sizeof(struct nfs4_label), flags); | ||
306 | if (label == NULL) | ||
307 | return ERR_PTR(-ENOMEM); | ||
308 | |||
309 | label->label = kzalloc(NFS4_MAXLABELLEN, flags); | ||
310 | if (label->label == NULL) { | ||
311 | kfree(label); | ||
312 | return ERR_PTR(-ENOMEM); | ||
313 | } | ||
314 | label->len = NFS4_MAXLABELLEN; | ||
315 | |||
316 | return label; | ||
317 | } | ||
318 | EXPORT_SYMBOL_GPL(nfs4_label_alloc); | ||
319 | #else | ||
320 | void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
321 | struct nfs4_label *label) | ||
322 | { | ||
323 | } | ||
324 | #endif | ||
325 | EXPORT_SYMBOL_GPL(nfs_setsecurity); | ||
326 | |||
260 | /* | 327 | /* |
261 | * This is our front-end to iget that looks up inodes by file handle | 328 | * This is our front-end to iget that looks up inodes by file handle |
262 | * instead of inode number. | 329 | * instead of inode number. |
263 | */ | 330 | */ |
264 | struct inode * | 331 | struct inode * |
265 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | 332 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label) |
266 | { | 333 | { |
267 | struct nfs_find_desc desc = { | 334 | struct nfs_find_desc desc = { |
268 | .fh = fh, | 335 | .fh = fh, |
@@ -384,6 +451,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
384 | */ | 451 | */ |
385 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 452 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
386 | } | 453 | } |
454 | |||
455 | nfs_setsecurity(inode, fattr, label); | ||
456 | |||
387 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 457 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
388 | nfsi->attrtimeo_timestamp = now; | 458 | nfsi->attrtimeo_timestamp = now; |
389 | nfsi->access_cache = RB_ROOT; | 459 | nfsi->access_cache = RB_ROOT; |
@@ -449,7 +519,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
449 | NFS_PROTO(inode)->return_delegation(inode); | 519 | NFS_PROTO(inode)->return_delegation(inode); |
450 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); | 520 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
451 | if (error == 0) | 521 | if (error == 0) |
452 | nfs_refresh_inode(inode, fattr); | 522 | error = nfs_refresh_inode(inode, fattr); |
453 | nfs_free_fattr(fattr); | 523 | nfs_free_fattr(fattr); |
454 | out: | 524 | out: |
455 | return error; | 525 | return error; |
@@ -713,16 +783,23 @@ EXPORT_SYMBOL_GPL(put_nfs_open_context); | |||
713 | * Ensure that mmap has a recent RPC credential for use when writing out | 783 | * Ensure that mmap has a recent RPC credential for use when writing out |
714 | * shared pages | 784 | * shared pages |
715 | */ | 785 | */ |
716 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | 786 | void nfs_inode_attach_open_context(struct nfs_open_context *ctx) |
717 | { | 787 | { |
718 | struct inode *inode = file_inode(filp); | 788 | struct inode *inode = ctx->dentry->d_inode; |
719 | struct nfs_inode *nfsi = NFS_I(inode); | 789 | struct nfs_inode *nfsi = NFS_I(inode); |
720 | 790 | ||
721 | filp->private_data = get_nfs_open_context(ctx); | ||
722 | spin_lock(&inode->i_lock); | 791 | spin_lock(&inode->i_lock); |
723 | list_add(&ctx->list, &nfsi->open_files); | 792 | list_add(&ctx->list, &nfsi->open_files); |
724 | spin_unlock(&inode->i_lock); | 793 | spin_unlock(&inode->i_lock); |
725 | } | 794 | } |
795 | EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context); | ||
796 | |||
797 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | ||
798 | { | ||
799 | filp->private_data = get_nfs_open_context(ctx); | ||
800 | if (list_empty(&ctx->list)) | ||
801 | nfs_inode_attach_open_context(ctx); | ||
802 | } | ||
726 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); | 803 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); |
727 | 804 | ||
728 | /* | 805 | /* |
@@ -748,10 +825,11 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
748 | 825 | ||
749 | static void nfs_file_clear_open_context(struct file *filp) | 826 | static void nfs_file_clear_open_context(struct file *filp) |
750 | { | 827 | { |
751 | struct inode *inode = file_inode(filp); | ||
752 | struct nfs_open_context *ctx = nfs_file_open_context(filp); | 828 | struct nfs_open_context *ctx = nfs_file_open_context(filp); |
753 | 829 | ||
754 | if (ctx) { | 830 | if (ctx) { |
831 | struct inode *inode = ctx->dentry->d_inode; | ||
832 | |||
755 | filp->private_data = NULL; | 833 | filp->private_data = NULL; |
756 | spin_lock(&inode->i_lock); | 834 | spin_lock(&inode->i_lock); |
757 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); | 835 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); |
@@ -790,6 +868,7 @@ int | |||
790 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 868 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
791 | { | 869 | { |
792 | int status = -ESTALE; | 870 | int status = -ESTALE; |
871 | struct nfs4_label *label = NULL; | ||
793 | struct nfs_fattr *fattr = NULL; | 872 | struct nfs_fattr *fattr = NULL; |
794 | struct nfs_inode *nfsi = NFS_I(inode); | 873 | struct nfs_inode *nfsi = NFS_I(inode); |
795 | 874 | ||
@@ -807,7 +886,14 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
807 | goto out; | 886 | goto out; |
808 | 887 | ||
809 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 888 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
810 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr); | 889 | |
890 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
891 | if (IS_ERR(label)) { | ||
892 | status = PTR_ERR(label); | ||
893 | goto out; | ||
894 | } | ||
895 | |||
896 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label); | ||
811 | if (status != 0) { | 897 | if (status != 0) { |
812 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 898 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
813 | inode->i_sb->s_id, | 899 | inode->i_sb->s_id, |
@@ -817,7 +903,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
817 | if (!S_ISDIR(inode->i_mode)) | 903 | if (!S_ISDIR(inode->i_mode)) |
818 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); | 904 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
819 | } | 905 | } |
820 | goto out; | 906 | goto err_out; |
821 | } | 907 | } |
822 | 908 | ||
823 | status = nfs_refresh_inode(inode, fattr); | 909 | status = nfs_refresh_inode(inode, fattr); |
@@ -825,7 +911,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
825 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 911 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
826 | inode->i_sb->s_id, | 912 | inode->i_sb->s_id, |
827 | (long long)NFS_FILEID(inode), status); | 913 | (long long)NFS_FILEID(inode), status); |
828 | goto out; | 914 | goto err_out; |
829 | } | 915 | } |
830 | 916 | ||
831 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) | 917 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
@@ -835,7 +921,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
835 | inode->i_sb->s_id, | 921 | inode->i_sb->s_id, |
836 | (long long)NFS_FILEID(inode)); | 922 | (long long)NFS_FILEID(inode)); |
837 | 923 | ||
838 | out: | 924 | err_out: |
925 | nfs4_label_free(label); | ||
926 | out: | ||
839 | nfs_free_fattr(fattr); | 927 | nfs_free_fattr(fattr); |
840 | return status; | 928 | return status; |
841 | } | 929 | } |
@@ -847,7 +935,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
847 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | 935 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); |
848 | } | 936 | } |
849 | 937 | ||
850 | static int nfs_attribute_cache_expired(struct inode *inode) | 938 | int nfs_attribute_cache_expired(struct inode *inode) |
851 | { | 939 | { |
852 | if (nfs_have_delegated_attributes(inode)) | 940 | if (nfs_have_delegated_attributes(inode)) |
853 | return 0; | 941 | return 0; |
@@ -863,7 +951,8 @@ static int nfs_attribute_cache_expired(struct inode *inode) | |||
863 | */ | 951 | */ |
864 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 952 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
865 | { | 953 | { |
866 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) | 954 | if (!(NFS_I(inode)->cache_validity & |
955 | (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) | ||
867 | && !nfs_attribute_cache_expired(inode)) | 956 | && !nfs_attribute_cache_expired(inode)) |
868 | return NFS_STALE(inode) ? -ESTALE : 0; | 957 | return NFS_STALE(inode) ? -ESTALE : 0; |
869 | return __nfs_revalidate_inode(server, inode); | 958 | return __nfs_revalidate_inode(server, inode); |
@@ -873,9 +962,15 @@ EXPORT_SYMBOL_GPL(nfs_revalidate_inode); | |||
873 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) | 962 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) |
874 | { | 963 | { |
875 | struct nfs_inode *nfsi = NFS_I(inode); | 964 | struct nfs_inode *nfsi = NFS_I(inode); |
876 | 965 | int ret; | |
966 | |||
877 | if (mapping->nrpages != 0) { | 967 | if (mapping->nrpages != 0) { |
878 | int ret = invalidate_inode_pages2(mapping); | 968 | if (S_ISREG(inode->i_mode)) { |
969 | ret = nfs_sync_mapping(mapping); | ||
970 | if (ret < 0) | ||
971 | return ret; | ||
972 | } | ||
973 | ret = invalidate_inode_pages2(mapping); | ||
879 | if (ret < 0) | 974 | if (ret < 0) |
880 | return ret; | 975 | return ret; |
881 | } | 976 | } |
@@ -1243,6 +1338,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1243 | spin_lock(&inode->i_lock); | 1338 | spin_lock(&inode->i_lock); |
1244 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1339 | status = nfs_post_op_update_inode_locked(inode, fattr); |
1245 | spin_unlock(&inode->i_lock); | 1340 | spin_unlock(&inode->i_lock); |
1341 | |||
1246 | return status; | 1342 | return status; |
1247 | } | 1343 | } |
1248 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1344 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
@@ -1483,7 +1579,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1483 | inode->i_blocks = fattr->du.nfs2.blocks; | 1579 | inode->i_blocks = fattr->du.nfs2.blocks; |
1484 | 1580 | ||
1485 | /* Update attrtimeo value if we're out of the unstable period */ | 1581 | /* Update attrtimeo value if we're out of the unstable period */ |
1486 | if (invalid & NFS_INO_INVALID_ATTR) { | 1582 | if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { |
1487 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1583 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1488 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1584 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1489 | nfsi->attrtimeo_timestamp = now; | 1585 | nfsi->attrtimeo_timestamp = now; |
@@ -1496,6 +1592,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1496 | } | 1592 | } |
1497 | } | 1593 | } |
1498 | invalid &= ~NFS_INO_INVALID_ATTR; | 1594 | invalid &= ~NFS_INO_INVALID_ATTR; |
1595 | invalid &= ~NFS_INO_INVALID_LABEL; | ||
1499 | /* Don't invalidate the data if we were to blame */ | 1596 | /* Don't invalidate the data if we were to blame */ |
1500 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1597 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1501 | || S_ISLNK(inode->i_mode))) | 1598 | || S_ISLNK(inode->i_mode))) |
@@ -1638,12 +1735,11 @@ EXPORT_SYMBOL_GPL(nfs_net_id); | |||
1638 | static int nfs_net_init(struct net *net) | 1735 | static int nfs_net_init(struct net *net) |
1639 | { | 1736 | { |
1640 | nfs_clients_init(net); | 1737 | nfs_clients_init(net); |
1641 | return nfs_dns_resolver_cache_init(net); | 1738 | return 0; |
1642 | } | 1739 | } |
1643 | 1740 | ||
1644 | static void nfs_net_exit(struct net *net) | 1741 | static void nfs_net_exit(struct net *net) |
1645 | { | 1742 | { |
1646 | nfs_dns_resolver_cache_destroy(net); | ||
1647 | nfs_cleanup_cb_ident_idr(net); | 1743 | nfs_cleanup_cb_ident_idr(net); |
1648 | } | 1744 | } |
1649 | 1745 | ||
@@ -1661,10 +1757,6 @@ static int __init init_nfs_fs(void) | |||
1661 | { | 1757 | { |
1662 | int err; | 1758 | int err; |
1663 | 1759 | ||
1664 | err = nfs_dns_resolver_init(); | ||
1665 | if (err < 0) | ||
1666 | goto out10;; | ||
1667 | |||
1668 | err = register_pernet_subsys(&nfs_net_ops); | 1760 | err = register_pernet_subsys(&nfs_net_ops); |
1669 | if (err < 0) | 1761 | if (err < 0) |
1670 | goto out9; | 1762 | goto out9; |
@@ -1730,8 +1822,6 @@ out7: | |||
1730 | out8: | 1822 | out8: |
1731 | unregister_pernet_subsys(&nfs_net_ops); | 1823 | unregister_pernet_subsys(&nfs_net_ops); |
1732 | out9: | 1824 | out9: |
1733 | nfs_dns_resolver_destroy(); | ||
1734 | out10: | ||
1735 | return err; | 1825 | return err; |
1736 | } | 1826 | } |
1737 | 1827 | ||
@@ -1744,7 +1834,6 @@ static void __exit exit_nfs_fs(void) | |||
1744 | nfs_destroy_nfspagecache(); | 1834 | nfs_destroy_nfspagecache(); |
1745 | nfs_fscache_unregister(); | 1835 | nfs_fscache_unregister(); |
1746 | unregister_pernet_subsys(&nfs_net_ops); | 1836 | unregister_pernet_subsys(&nfs_net_ops); |
1747 | nfs_dns_resolver_destroy(); | ||
1748 | #ifdef CONFIG_PROC_FS | 1837 | #ifdef CONFIG_PROC_FS |
1749 | rpc_proc_unregister(&init_net, "nfs"); | 1838 | rpc_proc_unregister(&init_net, "nfs"); |
1750 | #endif | 1839 | #endif |