diff options
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.h | 19 | ||||
-rw-r--r-- | fs/nfs/blocklayout/dev.c | 9 | ||||
-rw-r--r-- | fs/nfs/blocklayout/extent_tree.c | 19 | ||||
-rw-r--r-- | fs/nfs/callback.c | 4 | ||||
-rw-r--r-- | fs/nfs/callback_proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/client.c | 113 | ||||
-rw-r--r-- | fs/nfs/dir.c | 20 | ||||
-rw-r--r-- | fs/nfs/file.c | 3 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 13 | ||||
-rw-r--r-- | fs/nfs/inode.c | 8 | ||||
-rw-r--r-- | fs/nfs/internal.h | 19 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4idmap.c | 14 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 12 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 4 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 4 | ||||
-rw-r--r-- | fs/nfs/pnfs_nfs.c | 5 | ||||
-rw-r--r-- | fs/nfs/super.c | 7 | ||||
-rw-r--r-- | fs/nfs/write.c | 36 | ||||
-rw-r--r-- | fs/nfsd/blocklayoutxdr.c | 2 | ||||
-rw-r--r-- | fs/nfsd/blocklayoutxdr.h | 15 | ||||
-rw-r--r-- | include/linux/nfs4.h | 18 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/addr.h | 25 | ||||
-rw-r--r-- | include/linux/sunrpc/auth.h | 8 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 2 |
28 files changed, 138 insertions, 259 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 92dca9e90d8d..c556640dcf3b 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -46,13 +46,6 @@ struct pnfs_block_dev; -enum pnfs_block_volume_type { - PNFS_BLOCK_VOLUME_SIMPLE = 0, - PNFS_BLOCK_VOLUME_SLICE = 1, - PNFS_BLOCK_VOLUME_CONCAT = 2, - PNFS_BLOCK_VOLUME_STRIPE = 3, -}; - #define PNFS_BLOCK_MAX_UUIDS 4 #define PNFS_BLOCK_MAX_DEVICES 64 @@ -117,13 +110,6 @@ struct pnfs_block_dev { struct pnfs_block_dev_map *map); }; -enum exstate4 { - PNFS_BLOCK_READWRITE_DATA = 0, - PNFS_BLOCK_READ_DATA = 1, - PNFS_BLOCK_INVALID_DATA = 2, /* mapped, but data is invalid */ - PNFS_BLOCK_NONE_DATA = 3 /* unmapped, it's a hole */ -}; - /* sector_t fields are all in 512-byte sectors */ struct pnfs_block_extent { union { @@ -134,15 +120,12 @@ struct pnfs_block_extent { sector_t be_f_offset; /* the starting offset in the file */ sector_t be_length; /* the size of the extent */ sector_t be_v_offset; /* the starting offset in the volume */ - enum exstate4 be_state; /* the state of this extent */ + enum pnfs_block_extent_state be_state; /* the state of this extent */ #define EXTENT_WRITTEN 1 #define EXTENT_COMMITTING 2 unsigned int be_tag; }; -/* on the wire size of the extent */ -#define BL_EXTENT_SIZE (7 * sizeof(__be32) + NFS4_DEVICEID4_SIZE) - struct pnfs_block_layout { struct pnfs_layout_hdr bl_layout; struct rb_root bl_ext_rw; diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c index e535599a0719..a861bbdfe577 100644 --- a/fs/nfs/blocklayout/dev.c +++ b/fs/nfs/blocklayout/dev.c @@ -22,7 +22,7 @@ bl_free_device(struct pnfs_block_dev *dev) kfree(dev->children); } else { if (dev->bdev) - blkdev_put(dev->bdev, FMODE_READ); + blkdev_put(dev->bdev, FMODE_READ | FMODE_WRITE); } } @@ -65,6 +65,11 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b) return -EIO; p = xdr_decode_hyper(p, &b->simple.sigs[i].offset); b->simple.sigs[i].sig_len = be32_to_cpup(p++); + if (b->simple.sigs[i].sig_len > PNFS_BLOCK_UUID_LEN) { + pr_info("signature too long: %d\n", + b->simple.sigs[i].sig_len); + return -EIO; + } p = xdr_inline_decode(xdr, b->simple.sigs[i].sig_len); if (!p) @@ -195,7 +200,7 @@ bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d, if (!dev) return -EIO; - d->bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL); + d->bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_WRITE, NULL); if (IS_ERR(d->bdev)) { printk(KERN_WARNING "pNFS: failed to open device %d:%d (%ld)\n", MAJOR(dev), MINOR(dev), PTR_ERR(d->bdev)); diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c index 31d0b5e53dfd..c59a59c37f3d 100644 --- a/fs/nfs/blocklayout/extent_tree.c +++ b/fs/nfs/blocklayout/extent_tree.c @@ -462,6 +462,12 @@ out: return err; } +static size_t ext_tree_layoutupdate_size(size_t count) +{ + return sizeof(__be32) /* number of entries */ + + PNFS_BLOCK_EXTENT_SIZE * count; +} + static void ext_tree_free_commitdata(struct nfs4_layoutcommit_args *arg, size_t buffer_size) { @@ -489,7 +495,7 @@ static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p, continue; (*count)++; - if (*count * BL_EXTENT_SIZE > buffer_size) { + if (ext_tree_layoutupdate_size(*count) > buffer_size) { /* keep counting.. */ ret = -ENOSPC; continue; @@ -530,7 +536,7 @@ retry: if (unlikely(ret)) { ext_tree_free_commitdata(arg, buffer_size); - buffer_size = sizeof(__be32) + BL_EXTENT_SIZE * count; + buffer_size = ext_tree_layoutupdate_size(count); count = 0; arg->layoutupdate_pages = @@ -549,17 +555,14 @@ retry: } *start_p = cpu_to_be32(count); - arg->layoutupdate_len = sizeof(__be32) + BL_EXTENT_SIZE * count; + arg->layoutupdate_len = ext_tree_layoutupdate_size(count); if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) { - __be32 *p = start_p; + void *p = start_p, *end = p + arg->layoutupdate_len; int i = 0; - for (p = start_p; - p < start_p + arg->layoutupdate_len; - p += PAGE_SIZE) { + for ( ; p < end; p += PAGE_SIZE) arg->layoutupdate_pages[i++] = vmalloc_to_page(p); - } } dprintk("%s found %zu ranges\n", __func__, count); diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 682529c00996..6d27d7215a21 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -162,10 +162,6 @@ nfs41_callback_up(struct svc_serv *serv) spin_lock_init(&serv->sv_cb_lock); init_waitqueue_head(&serv->sv_cb_waitq); rqstp = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); - if (IS_ERR(rqstp)) { - svc_xprt_put(serv->sv_bc_xprt); - serv->sv_bc_xprt = NULL; - } dprintk("--> %s return %d\n", __func__, PTR_ERR_OR_ZERO(rqstp)); return rqstp; } diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 29e3c1b011b7..624bef79ba7c 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -554,7 +554,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy, status = htonl(NFS4_OK); nfs41_set_target_slotid(fc_tbl, args->crsa_target_highest_slotid); - nfs41_server_notify_target_slotid_update(cps->clp); + nfs41_notify_server(cps->clp); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); return status; diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4a90c9bb3135..57c5a02f6213 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -20,6 +20,7 @@ #include <linux/stat.h> #include <linux/errno.h> #include <linux/unistd.h> +#include <linux/sunrpc/addr.h> #include <linux/sunrpc/clnt.h> #include <linux/sunrpc/stats.h> #include <linux/sunrpc/metrics.h> @@ -285,116 +286,6 @@ void nfs_put_client(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs_put_client); -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -/* - * Test if two ip6 socket addresses refer to the same socket by - * comparing relevant fields. The padding bytes specifically, are not - * compared. sin6_flowinfo is not compared because it only affects QoS - * and sin6_scope_id is only compared if the address is "link local" - * because "link local" addresses need only be unique to a specific - * link. Conversely, ordinary unicast addresses might have different - * sin6_scope_id. - * - * The caller should ensure both socket addresses are AF_INET6. - */ -static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; - const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; - - if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) - return 0; - else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL) - return sin1->sin6_scope_id == sin2->sin6_scope_id; - - return 1; -} -#else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ -static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - return 0; -} -#endif - -/* - * Test if two ip4 socket addresses refer to the same socket, by - * comparing relevant fields. The padding bytes specifically, are - * not compared. - * - * The caller should ensure both socket addresses are AF_INET. - */ -static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; - const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; - - return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; -} - -static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; - const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; - - return nfs_sockaddr_match_ipaddr6(sa1, sa2) && - (sin1->sin6_port == sin2->sin6_port); -} - -static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; - const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; - - return nfs_sockaddr_match_ipaddr4(sa1, sa2) && - (sin1->sin_port == sin2->sin_port); -} - -#if defined(CONFIG_NFS_V4_1) -/* - * Test if two socket addresses represent the same actual socket, - * by comparing (only) relevant fields, excluding the port number. - */ -int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - if (sa1->sa_family != sa2->sa_family) - return 0; - - switch (sa1->sa_family) { - case AF_INET: - return nfs_sockaddr_match_ipaddr4(sa1, sa2); - case AF_INET6: - return nfs_sockaddr_match_ipaddr6(sa1, sa2); - } - return 0; -} -EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr); -#endif /* CONFIG_NFS_V4_1 */ - -/* - * Test if two socket addresses represent the same actual socket, - * by comparing (only) relevant fields, including the port number. - */ -static int nfs_sockaddr_cmp(const struct sockaddr *sa1, - const struct sockaddr *sa2) -{ - if (sa1->sa_family != sa2->sa_family) - return 0; - - switch (sa1->sa_family) { - case AF_INET: - return nfs_sockaddr_cmp_ip4(sa1, sa2); - case AF_INET6: - return nfs_sockaddr_cmp_ip6(sa1, sa2); - } - return 0; -} - /* * Find an nfs_client on the list that matches the initialisation data * that is supplied. @@ -421,7 +312,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat if (clp->cl_minorversion != data->minorversion) continue; /* Match the full socket address */ - if (!nfs_sockaddr_cmp(sap, clap)) + if (!rpc_cmp_addr_port(sap, clap)) continue; atomic_inc(&clp->cl_count); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 547308a5ec6f..3d8e4ffa0a33 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -583,26 +583,19 @@ out_nopages: } static -void nfs_readdir_free_pagearray(struct page **pages, unsigned int npages) +void nfs_readdir_free_pages(struct page **pages, unsigned int npages) { unsigned int i; for (i = 0; i < npages; i++) put_page(pages[i]); } -static -void nfs_readdir_free_large_page(void *ptr, struct page **pages, - unsigned int npages) -{ - nfs_readdir_free_pagearray(pages, npages); -} - /* * nfs_readdir_large_page will allocate pages that must be freed with a call - * to nfs_readdir_free_large_page + * to nfs_readdir_free_pagearray */ static -int nfs_readdir_large_page(struct page **pages, unsigned int npages) +int nfs_readdir_alloc_pages(struct page **pages, unsigned int npages) { unsigned int i; @@ -615,7 +608,7 @@ int nfs_readdir_large_page(struct page **pages, unsigned int npages) return 0; out_freepages: - nfs_readdir_free_pagearray(pages, i); + nfs_readdir_free_pages(pages, i); return -ENOMEM; } @@ -623,7 +616,6 @@ static int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode) { struct page *pages[NFS_MAX_READDIR_PAGES]; - void *pages_ptr = NULL; struct nfs_entry entry; struct file *file = desc->file; struct nfs_cache_array *array; @@ -653,7 +645,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, memset(array, 0, sizeof(struct nfs_cache_array)); array->eof_index = -1; - status = nfs_readdir_large_page(pages, array_size); + status = nfs_readdir_alloc_pages(pages, array_size); if (status < 0) goto out_release_array; do { @@ -671,7 +663,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, } } while (array->eof_index < 0); - nfs_readdir_free_large_page(pages_ptr, pages, array_size); + nfs_readdir_free_pages(pages, array_size); out_release_array: nfs_readdir_release_array(page); out_label_free: diff --git a/fs/nfs/file.c b/fs/nfs/file.c index cc4fa1ed61fc..7538a8582384 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -82,7 +82,8 @@ nfs_file_release(struct inode *inode, struct file *filp) dprintk("NFS: release(%pD2)\n", filp); nfs_inc_stats(inode, NFSIOS_VFSRELEASE); - return nfs_release(inode, filp); + nfs_file_clear_open_context(filp); + return 0; } EXPORT_SYMBOL_GPL(nfs_file_release); diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index b3289d701eea..13fe64b4e259 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -510,7 +510,8 @@ nfs4_ff_layout_stat_io_start_read(struct nfs4_ff_layout_mirror *mirror, spin_unlock(&mirror->lock); if (report) - pnfs_report_layoutstat(mirror->lseg->pls_layout->plh_inode); + pnfs_report_layoutstat(mirror->lseg->pls_layout->plh_inode, + GFP_KERNEL); } static void @@ -538,7 +539,8 @@ nfs4_ff_layout_stat_io_start_write(struct nfs4_ff_layout_mirror *mirror, spin_unlock(&mirror->lock); if (report) - pnfs_report_layoutstat(mirror->lseg->pls_layout->plh_inode); + pnfs_report_layoutstat(mirror->lseg->pls_layout->plh_inode, + GFP_NOIO); } static void @@ -728,8 +730,6 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg); /* no lseg means that pnfs is not in use, so no mirroring here */ - pnfs_put_lseg(pgio->pg_lseg); - pgio->pg_lseg = NULL; nfs_pageio_reset_write_mds(pgio); return 1; } @@ -1863,10 +1863,9 @@ ff_layout_mirror_prepare_stats(struct nfs42_layoutstat_args *args, memcpy(&devinfo->dev_id, &dev->deviceid, NFS4_DEVICEID4_SIZE); devinfo->offset = pls->pls_range.offset; devinfo->length = pls->pls_range.length; - /* well, we don't really know if IO is continuous or not! */ - devinfo->read_count = mirror->read_stat.io_stat.bytes_completed; + devinfo->read_count = mirror->read_stat.io_stat.ops_completed; devinfo->read_bytes = mirror->read_stat.io_stat.bytes_completed; - devinfo->write_count = mirror->write_stat.io_stat.bytes_completed; + devinfo->write_count = mirror->write_stat.io_stat.ops_completed; devinfo->write_bytes = mirror->write_stat.io_stat.bytes_completed; devinfo->layout_type = LAYOUT_FLEX_FILES; devinfo->layoutstats_encode = ff_layout_encode_layoutstats; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 0adc7d245b3d..382c8a46c078 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -888,7 +888,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c return ctx; } -static void nfs_file_clear_open_context(struct file *filp) +void nfs_file_clear_open_context(struct file *filp) { struct nfs_open_context *ctx = nfs_file_open_context(filp); @@ -919,12 +919,6 @@ int nfs_open(struct inode *inode, struct file *filp) return 0; } -int nfs_release(struct inode *inode, struct file *filp) -{ - nfs_file_clear_open_context(filp); - return 0; -} - /* * This function is called whenever some part of NFS notices that * the cached attributes have to be refreshed. diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 9b372b845f6a..9ab3b1c21bb4 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -219,10 +219,6 @@ static inline void nfs_fs_proc_exit(void) } #endif -#ifdef CONFIG_NFS_V4_1 -int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *); -#endif - /* callback_xdr.c */ extern struct svc_version nfs4_callback_version1; extern struct svc_version nfs4_callback_version4; @@ -490,6 +486,9 @@ void nfs_retry_commit(struct list_head *page_list, void nfs_commitdata_release(struct nfs_commit_data *data); void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, struct nfs_commit_info *cinfo); +void nfs_request_add_commit_list_locked(struct nfs_page *req, + struct list_head *dst, + struct nfs_commit_info *cinfo); void nfs_request_remove_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo); void nfs_init_cinfo(struct nfs_commit_info *cinfo, @@ -623,13 +622,15 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) * Record the page as unstable and mark its inode as dirty. */ static inline -void nfs_mark_page_unstable(struct page *page) +void nfs_mark_page_unstable(struct page *page, struct nfs_commit_info *cinfo) { - struct inode *inode = page_file_mapping(page)->host; + if (!cinfo->dreq) { + struct inode *inode = page_file_mapping(page)->host; - inc_zone_page_state(page, NR_UNSTABLE_NFS); - inc_wb_stat(&inode_to_bdi(inode)->wb, WB_RECLAIMABLE); - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + inc_zone_page_state(page, NR_UNSTABLE_NFS); + inc_wb_stat(&inode_to_bdi(inode)->wb, WB_RECLAIMABLE); + __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + } } /* diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ea3bee919a76..50cfc4ca7a02 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -405,9 +405,7 @@ int nfs40_discover_server_trunking(struct nfs_client *clp, int nfs41_discover_server_trunking(struct nfs_client *clp, struct nfs_client **, struct rpc_cred *); extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); -extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp); -extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp); - +extern void nfs41_notify_server(struct nfs_client *); #else static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) { diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 3aa6a9ba5113..223bedda64ae 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -729,10 +729,7 @@ static bool nfs4_cb_match_client(const struct sockaddr *addr, return false; /* Match only the IP address, not the port number */ - if (!nfs_sockaddr_match_ipaddr(addr, clap)) - return false; - - return true; + return rpc_cmp_addr(addr, clap); } /* diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index 535dfc69c628..2e4902203c35 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c @@ -184,7 +184,7 @@ static struct key_type key_type_id_resolver = { .read = user_read, }; -static int nfs_idmap_init_keyring(void) +int nfs_idmap_init(void) { struct cred *cred; struct key *keyring; @@ -230,7 +230,7 @@ failed_put_cred: return ret; } -static void nfs_idmap_quit_keyring(void) +void nfs_idmap_quit(void) { key_revoke(id_resolver_cache->thread_keyring); unregister_key_type(&key_type_id_resolver); @@ -492,16 +492,6 @@ nfs_idmap_delete(struct nfs_client *clp) kfree(idmap); } -int nfs_idmap_init(void) -{ - return nfs_idmap_init_keyring(); -} - -void nfs_idmap_quit(void) -{ - nfs_idmap_quit_keyring(); -} - static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, struct idmap_msg *im, struct rpc_pipe_msg *msg) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3acb1eb72930..f4e5816a77b0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -586,7 +586,7 @@ out_unlock: spin_unlock(&tbl->slot_tbl_lock); res->sr_slot = NULL; if (send_new_highest_used_slotid) - nfs41_server_notify_highest_slotid_update(session->clp); + nfs41_notify_server(session->clp); } int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) @@ -2425,7 +2425,7 @@ static int _nfs4_do_open(struct inode *dir, goto err_free_label; state = ctx->state; - if ((opendata->o_arg.open_flags & O_EXCL) && + if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) && (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { nfs4_exclusive_attrset(opendata, sattr); @@ -8661,6 +8661,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { .reboot_recovery_ops = &nfs41_reboot_recovery_ops, .nograce_recovery_ops = &nfs41_nograce_recovery_ops, .state_renewal_ops = &nfs41_state_renewal_ops, + .mig_recovery_ops = &nfs41_mig_recovery_ops, }; #endif diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f2e2ad894461..da73bc443238 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -2152,23 +2152,13 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) } EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); -static void nfs41_ping_server(struct nfs_client *clp) +void nfs41_notify_server(struct nfs_client *clp) { /* Use CHECK_LEASE to ping the server with a SEQUENCE */ set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); nfs4_schedule_state_manager(clp); } -void nfs41_server_notify_target_slotid_update(struct nfs_client *clp) -{ - nfs41_ping_server(clp); -} - -void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp) -{ - nfs41_ping_server(clp); -} - static void nfs4_reset_all_state(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 70bf706b1090..a6ec420983d1 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -2267,7 +2267,7 @@ struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) #if IS_ENABLED(CONFIG_NFS_V4_2) int -pnfs_report_layoutstat(struct inode *inode) +pnfs_report_layoutstat(struct inode *inode, gfp_t gfp_flags) { struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; struct nfs_server *server = NFS_SERVER(inode); @@ -2294,7 +2294,7 @@ pnfs_report_layoutstat(struct inode *inode) pnfs_get_layout_hdr(hdr); spin_unlock(&inode->i_lock); - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), gfp_flags); if (!data) { status = -ENOMEM; goto out_put; diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 3e6ab7bfbabd..738672a0f8da 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -691,10 +691,10 @@ static inline void nfs4_pnfs_v3_ds_connect_unload(void) #endif /* CONFIG_NFS_V4_1 */ #if IS_ENABLED(CONFIG_NFS_V4_2) -int pnfs_report_layoutstat(struct inode *inode); +int pnfs_report_layoutstat(struct inode *inode, gfp_t gfp_flags); #else static inline int -pnfs_report_layoutstat(struct inode *inode) +pnfs_report_layoutstat(struct inode *inode, gfp_t gfp_flags) { return 0; } diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index f37e25b6311c..7a282876662f 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c @@ -863,9 +863,10 @@ pnfs_layout_mark_request_commit(struct nfs_page *req, } set_bit(PG_COMMIT_TO_DS, &req->wb_flags); cinfo->ds->nwritten++; - spin_unlock(cinfo->lock); - nfs_request_add_commit_list(req, list, cinfo); + nfs_request_add_commit_list_locked(req, list, cinfo); + spin_unlock(cinfo->lock); + nfs_mark_page_unstable(req->wb_page, cinfo); } EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index aa62004f1706..383a027de452 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -381,9 +381,12 @@ int __init register_nfs_fs(void) ret = nfs_register_sysctl(); if (ret < 0) goto error_2; - register_shrinker(&acl_shrinker); + ret = register_shrinker(&acl_shrinker); + if (ret < 0) + goto error_3; return 0; - +error_3: + nfs_unregister_sysctl(); error_2: unregister_nfs4_fs(); error_1: diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 75a35a1afa79..388f48079c43 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -768,6 +768,28 @@ nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi, } /** + * nfs_request_add_commit_list_locked - add request to a commit list + * @req: pointer to a struct nfs_page + * @dst: commit list head + * @cinfo: holds list lock and accounting info + * + * This sets the PG_CLEAN bit, updates the cinfo count of + * number of outstanding requests requiring a commit as well as + * the MM page stats. + * + * The caller must hold the cinfo->lock, and the nfs_page lock. + */ +void +nfs_request_add_commit_list_locked(struct nfs_page *req, struct list_head *dst, + struct nfs_commit_info *cinfo) +{ + set_bit(PG_CLEAN, &req->wb_flags); + nfs_list_add_request(req, dst); + cinfo->mds->ncommit++; +} +EXPORT_SYMBOL_GPL(nfs_request_add_commit_list_locked); + +/** * nfs_request_add_commit_list - add request to a commit list * @req: pointer to a struct nfs_page * @dst: commit list head @@ -784,13 +806,10 @@ void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, struct nfs_commit_info *cinfo) { - set_bit(PG_CLEAN, &(req)->wb_flags); spin_lock(cinfo->lock); - nfs_list_add_request(req, dst); - cinfo->mds->ncommit++; + nfs_request_add_commit_list_locked(req, dst, cinfo); spin_unlock(cinfo->lock); - if (!cinfo->dreq) - nfs_mark_page_unstable(req->wb_page); + nfs_mark_page_unstable(req->wb_page, cinfo); } EXPORT_SYMBOL_GPL(nfs_request_add_commit_list); @@ -1793,7 +1812,7 @@ out_mark_dirty: return res; } -static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) +int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) { struct nfs_inode *nfsi = NFS_I(inode); int flags = FLUSH_SYNC; @@ -1828,11 +1847,6 @@ out_mark_dirty: __mark_inode_dirty(inode, I_DIRTY_DATASYNC); return ret; } - -int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) -{ - return nfs_commit_unstable_pages(inode, wbc); -} EXPORT_SYMBOL_GPL(nfs_write_inode); /* diff --git a/fs/nfsd/blocklayoutxdr.c b/fs/nfsd/blocklayoutxdr.c index 9aa2796da90d..6d834dc9bbc8 100644 --- a/fs/nfsd/blocklayoutxdr.c +++ b/fs/nfsd/blocklayoutxdr.c @@ -101,7 +101,7 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, } nr_iomaps = be32_to_cpup(p++); - expected = sizeof(__be32) + nr_iomaps * NFS4_BLOCK_EXTENT_SIZE; + expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE; if (len != expected) { dprintk("%s: extent array size mismatch: %u/%u\n", __func__, len, expected); diff --git a/fs/nfsd/blocklayoutxdr.h b/fs/nfsd/blocklayoutxdr.h index fdc79037c0e7..6de925fe8499 100644 --- a/fs/nfsd/blocklayoutxdr.h +++ b/fs/nfsd/blocklayoutxdr.h @@ -7,13 +7,6 @@ struct iomap; struct xdr_stream; -enum pnfs_block_extent_state { - PNFS_BLOCK_READWRITE_DATA = 0, - PNFS_BLOCK_READ_DATA = 1, - PNFS_BLOCK_INVALID_DATA = 2, - PNFS_BLOCK_NONE_DATA = 3, -}; - struct pnfs_block_extent { struct nfsd4_deviceid vol_id; u64 foff; @@ -21,14 +14,6 @@ struct pnfs_block_extent { u64 soff; enum pnfs_block_extent_state es; }; -#define NFS4_BLOCK_EXTENT_SIZE 44 - -enum pnfs_block_volume_type { - PNFS_BLOCK_VOLUME_SIMPLE = 0, - PNFS_BLOCK_VOLUME_SLICE = 1, - PNFS_BLOCK_VOLUME_CONCAT = 2, - PNFS_BLOCK_VOLUME_STRIPE = 3, -}; /* * Random upper cap for the uuid length to avoid unbounded allocation. diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index b8e72aad919c..00121f298269 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -547,6 +547,24 @@ enum pnfs_notify_deviceid_type4 { NOTIFY_DEVICEID4_DELETE = 1 << 2, }; +enum pnfs_block_volume_type { + PNFS_BLOCK_VOLUME_SIMPLE = 0, + PNFS_BLOCK_VOLUME_SLICE = 1, + PNFS_BLOCK_VOLUME_CONCAT = 2, + PNFS_BLOCK_VOLUME_STRIPE = 3, +}; + +enum pnfs_block_extent_state { + PNFS_BLOCK_READWRITE_DATA = 0, + PNFS_BLOCK_READ_DATA = 1, + PNFS_BLOCK_INVALID_DATA = 2, + PNFS_BLOCK_NONE_DATA = 3, +}; + +/* on the wire size of a block layout extent */ +#define PNFS_BLOCK_EXTENT_SIZE \ + (7 * sizeof(__be32) + NFS4_DEVICEID4_SIZE) + #define NFL4_UFLG_MASK 0x0000003F #define NFL4_UFLG_DENSE 0x00000001 #define NFL4_UFLG_COMMIT_THRU_MDS 0x00000002 diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 874b77228fb9..c0e961474a52 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -353,7 +353,6 @@ extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern void nfs_access_set_mask(struct nfs_access_entry *, u32); extern int nfs_permission(struct inode *, int); extern int nfs_open(struct inode *, struct file *); -extern int nfs_release(struct inode *, struct file *); extern int nfs_attribute_timeout(struct inode *inode); extern int nfs_attribute_cache_expired(struct inode *inode); extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); @@ -371,6 +370,7 @@ extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struc extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode); extern void nfs_inode_attach_open_context(struct nfs_open_context *ctx); extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); +extern void nfs_file_clear_open_context(struct file *flip); extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); extern u64 nfs_compat_user_ino64(u64 fileid); diff --git a/include/linux/sunrpc/addr.h b/include/linux/sunrpc/addr.h index 07d8e53bedfc..9bc3538d09a9 100644 --- a/include/linux/sunrpc/addr.h +++ b/include/linux/sunrpc/addr.h @@ -46,8 +46,8 @@ static inline void rpc_set_port(struct sockaddr *sap, #define IPV6_SCOPE_DELIMITER '%' #define IPV6_SCOPE_ID_LEN sizeof("%nnnnnnnnnn") -static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1, - const struct sockaddr *sap2) +static inline bool rpc_cmp_addr4(const struct sockaddr *sap1, + const struct sockaddr *sap2) { const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1; const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2; @@ -67,8 +67,8 @@ static inline bool __rpc_copy_addr4(struct sockaddr *dst, } #if IS_ENABLED(CONFIG_IPV6) -static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, - const struct sockaddr *sap2) +static inline bool rpc_cmp_addr6(const struct sockaddr *sap1, + const struct sockaddr *sap2) { const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1; const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2; @@ -122,15 +122,28 @@ static inline bool rpc_cmp_addr(const struct sockaddr *sap1, if (sap1->sa_family == sap2->sa_family) { switch (sap1->sa_family) { case AF_INET: - return __rpc_cmp_addr4(sap1, sap2); + return rpc_cmp_addr4(sap1, sap2); case AF_INET6: - return __rpc_cmp_addr6(sap1, sap2); + return rpc_cmp_addr6(sap1, sap2); } } return false; } /** + * rpc_cmp_addr_port - compare the address and port number of two sockaddrs. + * @sap1: first sockaddr + * @sap2: second sockaddr + */ +static inline bool rpc_cmp_addr_port(const struct sockaddr *sap1, + const struct sockaddr *sap2) +{ + if (!rpc_cmp_addr(sap1, sap2)) + return false; + return rpc_get_port(sap1) == rpc_get_port(sap2); +} + +/** * rpc_copy_addr - copy the address portion of one sockaddr to another * @dst: destination sockaddr * @src: source sockaddr diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index a7cbb570cc5c..1ecf13e148b8 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -18,9 +18,13 @@ #include <linux/atomic.h> #include <linux/rcupdate.h> #include <linux/uidgid.h> +#include <linux/utsname.h> -/* size of the nodename buffer */ -#define UNX_MAXNODENAME 32 +/* + * Size of the nodename buffer. RFC1831 specifies a hard limit of 255 bytes, + * but Linux hostnames are actually limited to __NEW_UTS_LEN bytes. + */ +#define UNX_MAXNODENAME __NEW_UTS_LEN struct rpcsec_gss_info; diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 4feda2d0a833..548240dd15fc 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -23,7 +23,7 @@ struct unx_cred { }; #define uc_uid uc_base.cr_uid -#define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2)) +#define UNX_WRITESLACK (21 + XDR_QUADLEN(UNX_MAXNODENAME)) #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH |