From 6b1ba797ae21de6c13d43556335227cc4de8c533 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 9 Oct 2002 21:05:19 -0700 Subject: [PATCH] remove radix_tree_reserve() From Hugh Dickins. radix_tree_reserve() exists solely for the tmpfs move_to_swap_cache() and move_from_swap_cache() functions, and yet they don't need it: there is no problem in the one page being simultaneously listed in two radix trees (while both locks are held). Use radix_tree_insert(), and remove radix_tree_reserve(); also removed a few blank lines. --- include/linux/radix-tree.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 56d1c668ff2e..4e58eb79abeb 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -21,8 +21,6 @@ struct radix_tree_node; -#define RADIX_TREE_SLOT_RESERVED ((void *)~0UL) - struct radix_tree_root { unsigned int height; int gfp_mask; @@ -41,7 +39,6 @@ do { \ (root)->rnode = NULL; \ } while (0) -extern int radix_tree_reserve(struct radix_tree_root *, unsigned long, void ***); extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long); extern int radix_tree_delete(struct radix_tree_root *, unsigned long); -- cgit v1.2.3 From 59cc52713b7c37e9dcfda842b78c497968f41075 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 9 Oct 2002 22:38:51 -0700 Subject: [PATCH] add PCI device ID for Motorola MPC107 This patch adds the PCI device ID for the Motorola MPC107 host bridge. The entry is already in the list at pciids.sf.net but isn't in the kernel pci_ids.h file yet. Please apply this to your tree. --- include/linux/pci_ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 69c782cef0da..902158728595 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -623,6 +623,7 @@ #define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507 #define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001 #define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002 +#define PCI_DEVICE_ID_MOTOROLA_MPC107 0x0004 #define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801 #define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802 #define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803 -- cgit v1.2.3 From 4e956d0f08802becba081fd427f3bb55a0b715bf Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:45:49 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x Instantiate a new file, include/linux/nfs4.h, which contains constants and typedef's for the NFSv4 protocol (by analogy with include/linux/nfs2.h and include/linux/nfs3.h). Also #include this file in a few places where it will be needed later. --- fs/nfs/pagelist.c | 1 + include/linux/nfs4.h | 205 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs_fs.h | 1 + include/linux/nfsd/const.h | 1 + 4 files changed, 208 insertions(+) create mode 100644 include/linux/nfs4.h (limited to 'include/linux') diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index d9349d2dd2b1..827286b67d4b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h new file mode 100644 index 000000000000..d320dd969b07 --- /dev/null +++ b/include/linux/nfs4.h @@ -0,0 +1,205 @@ +/* + * include/linux/nfs4.h + * + * NFSv4 protocol definitions. + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Kendrick Smith + * Andy Adamson + */ + +#ifndef _LINUX_NFS4_H +#define _LINUX_NFS4_H + +#define NFS4_VERIFIER_SIZE 8 +#define NFS4_FHSIZE 128 +#define NFS4_MAXNAMLEN NAME_MAX + +#define NFS4_ACCESS_READ 0x0001 +#define NFS4_ACCESS_LOOKUP 0x0002 +#define NFS4_ACCESS_MODIFY 0x0004 +#define NFS4_ACCESS_EXTEND 0x0008 +#define NFS4_ACCESS_DELETE 0x0010 +#define NFS4_ACCESS_EXECUTE 0x0020 + +#define NFS4_FH_PERISTENT 0x0000 +#define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001 +#define NFS4_FH_VOLATILE_ANY 0x0002 +#define NFS4_FH_VOL_MIGRATION 0x0004 +#define NFS4_FH_VOL_RENAME 0x0008 + +#define NFS4_OPEN_RESULT_CONFIRM 0x0002 + +#define NFS4_SHARE_ACCESS_READ 0x0001 +#define NFS4_SHARE_ACCESS_WRITE 0x0002 +#define NFS4_SHARE_ACCESS_BOTH 0x0003 + +#define NFS4_SET_TO_SERVER_TIME 0 +#define NFS4_SET_TO_CLIENT_TIME 1 + +#define NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE 0 +#define NFS4_ACE_ACCESS_DENIED_ACE_TYPE 1 +#define NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE 2 +#define NFS4_ACE_SYSTEM_ALARM_ACE_TYPE 3 + +typedef char nfs4_verifier[NFS4_VERIFIER_SIZE]; +typedef char nfs4_stateid[16]; + +enum nfs_opnum4 { + OP_ACCESS = 3, + OP_CLOSE = 4, + OP_COMMIT = 5, + OP_CREATE = 6, + OP_DELEGPURGE = 7, + OP_DELEGRETURN = 8, + OP_GETATTR = 9, + OP_GETFH = 10, + OP_LINK = 11, + OP_LOCK = 12, + OP_LOCKT = 13, + OP_LOCKU = 14, + OP_LOOKUP = 15, + OP_LOOKUPP = 16, + OP_NVERIFY = 17, + OP_OPEN = 18, + OP_OPENATTR = 19, + OP_OPEN_CONFIRM = 20, + OP_OPEN_DOWNGRADE = 21, + OP_PUTFH = 22, + OP_PUTPUBFH = 23, + OP_PUTROOTFH = 24, + OP_READ = 25, + OP_READDIR = 26, + OP_READLINK = 27, + OP_REMOVE = 28, + OP_RENAME = 29, + OP_RENEW = 30, + OP_RESTOREFH = 31, + OP_SAVEFH = 32, + OP_SECINFO = 33, + OP_SETATTR = 34, + OP_SETCLIENTID = 35, + OP_SETCLIENTID_CONFIRM = 36, + OP_VERIFY = 37, + OP_WRITE = 38, +}; + +/* + * Note: NF4BAD is not actually part of the protocol; it is just used + * internally by nfsd. + */ +enum nfs_ftype4 { + NF4BAD = 0, + NF4REG = 1, /* Regular File */ + NF4DIR = 2, /* Directory */ + NF4BLK = 3, /* Special File - block device */ + NF4CHR = 4, /* Special File - character device */ + NF4LNK = 5, /* Symbolic Link */ + NF4SOCK = 6, /* Special File - socket */ + NF4FIFO = 7, /* Special File - fifo */ + NF4ATTRDIR = 8, /* Attribute Directory */ + NF4NAMEDATTR = 9 /* Named Attribute */ +}; + +enum open_claim_type4 { + NFS4_OPEN_CLAIM_NULL = 0, + NFS4_OPEN_CLAIM_PREVIOUS = 1, + NFS4_OPEN_CLAIM_DELEGATE_CUR = 2, + NFS4_OPEN_CLAIM_DELEGATE_PREV = 3 +}; + +enum opentype4 { + NFS4_OPEN_NOCREATE = 0, + NFS4_OPEN_CREATE = 1 +}; + +enum createmode4 { + NFS4_CREATE_UNCHECKED = 0, + NFS4_CREATE_GUARDED = 1, + NFS4_CREATE_EXCLUSIVE = 2 +}; + +enum limit_by4 { + NFS4_LIMIT_SIZE = 1, + NFS4_LIMIT_BLOCKS = 2 +}; + +enum open_delegation_type4 { + NFS4_OPEN_DELEGATE_NONE = 0, + NFS4_OPEN_DELEGATE_READ = 1, + NFS4_OPEN_DELEGATE_WRITE = 2 +}; + +/* Mandatory Attributes */ +#define FATTR4_WORD0_SUPPORTED_ATTRS (1) +#define FATTR4_WORD0_TYPE (1 << 1) +#define FATTR4_WORD0_FH_EXPIRE_TYPE (1 << 2) +#define FATTR4_WORD0_CHANGE (1 << 3) +#define FATTR4_WORD0_SIZE (1 << 4) +#define FATTR4_WORD0_LINK_SUPPORT (1 << 5) +#define FATTR4_WORD0_SYMLINK_SUPPORT (1 << 6) +#define FATTR4_WORD0_NAMED_ATTR (1 << 7) +#define FATTR4_WORD0_FSID (1 << 8) +#define FATTR4_WORD0_UNIQUE_HANDLES (1 << 9) +#define FATTR4_WORD0_LEASE_TIME (1 << 10) +#define FATTR4_WORD0_RDATTR_ERROR (1 << 11) + +/* Recommended Attributes */ +#define FATTR4_WORD0_ACL (1 << 12) +#define FATTR4_WORD0_ACLSUPPORT (1 << 13) +#define FATTR4_WORD0_ARCHIVE (1 << 14) +#define FATTR4_WORD0_CANSETTIME (1 << 15) +#define FATTR4_WORD0_CASE_INSENSITIVE (1 << 16) +#define FATTR4_WORD0_CASE_PRESERVING (1 << 17) +#define FATTR4_WORD0_CHOWN_RESTRICTED (1 << 18) +#define FATTR4_WORD0_FILEHANDLE (1 << 19) +#define FATTR4_WORD0_FILEID (1 << 20) +#define FATTR4_WORD0_FILES_AVAIL (1 << 21) +#define FATTR4_WORD0_FILES_FREE (1 << 22) +#define FATTR4_WORD0_FILES_TOTAL (1 << 23) +#define FATTR4_WORD0_FS_LOCATIONS (1 << 24) +#define FATTR4_WORD0_HIDDEN (1 << 25) +#define FATTR4_WORD0_HOMOGENEOUS (1 << 26) +#define FATTR4_WORD0_MAXFILESIZE (1 << 27) +#define FATTR4_WORD0_MAXLINK (1 << 28) +#define FATTR4_WORD0_MAXNAME (1 << 29) +#define FATTR4_WORD0_MAXREAD (1 << 30) +#define FATTR4_WORD0_MAXWRITE (1 << 31) +#define FATTR4_WORD1_MIMETYPE (1) +#define FATTR4_WORD1_MODE (1 << 1) +#define FATTR4_WORD1_NO_TRUNC (1 << 2) +#define FATTR4_WORD1_NUMLINKS (1 << 3) +#define FATTR4_WORD1_OWNER (1 << 4) +#define FATTR4_WORD1_OWNER_GROUP (1 << 5) +#define FATTR4_WORD1_QUOTA_HARD (1 << 6) +#define FATTR4_WORD1_QUOTA_SOFT (1 << 7) +#define FATTR4_WORD1_QUOTA_USED (1 << 8) +#define FATTR4_WORD1_RAWDEV (1 << 9) +#define FATTR4_WORD1_SPACE_AVAIL (1 << 10) +#define FATTR4_WORD1_SPACE_FREE (1 << 11) +#define FATTR4_WORD1_SPACE_TOTAL (1 << 12) +#define FATTR4_WORD1_SPACE_USED (1 << 13) +#define FATTR4_WORD1_SYSTEM (1 << 14) +#define FATTR4_WORD1_TIME_ACCESS (1 << 15) +#define FATTR4_WORD1_TIME_ACCESS_SET (1 << 16) +#define FATTR4_WORD1_TIME_BACKUP (1 << 17) +#define FATTR4_WORD1_TIME_CREATE (1 << 18) +#define FATTR4_WORD1_TIME_DELTA (1 << 19) +#define FATTR4_WORD1_TIME_METADATA (1 << 20) +#define FATTR4_WORD1_TIME_MODIFY (1 << 21) +#define FATTR4_WORD1_TIME_MODIFY_SET (1 << 22) + +#define NFSPROC4_NULL 0 +#define NFSPROC4_COMPOUND 1 +#define NFS4_MINOR_VERSION 0 +#define NFS4_DEBUG 1 + +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 42f716fd142f..b06a0c254838 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h index bd828fa0314f..623d577ca1b5 100644 --- a/include/linux/nfsd/const.h +++ b/include/linux/nfsd/const.h @@ -12,6 +12,7 @@ #include #include #include +#include /* * Maximum protocol version supported by knfsd -- cgit v1.2.3 From 944b2a7cd12c7f7b4146e559faab3351e13e19a3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:46:18 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x In a number of places in the NFS client, I had to change #ifdef CONFIG_NFS_V3 /* ... */ #endif to #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /* ... */ #endif --- fs/nfs/flushd.c | 2 +- fs/nfs/pagelist.c | 2 +- fs/nfs/write.c | 18 +++++++++--------- include/linux/nfs_fs.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/flushd.c b/fs/nfs/flushd.c index c636ab35f8f8..979a1163e68b 100644 --- a/fs/nfs/flushd.c +++ b/fs/nfs/flushd.c @@ -171,7 +171,7 @@ nfs_flushd(struct rpc_task *task) nfs_pagein_list(&head, server->rpages); continue; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (nfs_scan_lru_commit_timeout(server, &head)) { spin_unlock(&nfs_wreq_lock); nfs_commit_list(&head, FLUSH_AGING); diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 827286b67d4b..c2b2ffab43b8 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -507,7 +507,7 @@ nfs_try_to_free_pages(struct nfs_server *server) continue; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /* Let's try to free up some completed NFSv3 unstable writes */ nfs_scan_lru_commit(server, &head); if (!list_empty(&head)) { diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ae118cb1f28c..a1e8bf8db389 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -88,7 +88,7 @@ static struct nfs_page * nfs_update_request(struct file*, struct inode *, unsigned int, unsigned int); static void nfs_strategy(struct inode *inode); static void nfs_writeback_done(struct rpc_task *); -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) static void nfs_commit_done(struct rpc_task *); #endif @@ -414,7 +414,7 @@ nfs_dirty_request(struct nfs_page *req) return !list_empty(&req->wb_list) && req->wb_list_head == &nfsi->dirty; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /* * Add a request to the inode's commit list. */ @@ -552,7 +552,7 @@ nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, un return res; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /** * nfs_scan_lru_commit_timeout - Scan LRU list for timed out commit requests * @server: NFS superblock data @@ -747,7 +747,7 @@ nfs_strategy(struct inode *inode) dirty = NFS_I(inode)->ndirty; wpages = NFS_SERVER(inode)->wpages; -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (NFS_PROTO(inode)->version == 2) { if (dirty >= NFS_STRATEGY_PAGES * wpages) nfs_flush_file(inode, NULL, 0, 0, 0); @@ -1032,7 +1032,7 @@ nfs_writeback_done(struct rpc_task *task) * an error. */ task->tk_status = -EIO; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (resp->verf->committed < argp->stable && task->tk_status >= 0) { /* We tried a write call, but the server did not * commit data to stable storage even though we @@ -1082,7 +1082,7 @@ nfs_writeback_done(struct rpc_task *task) goto next; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (argp->stable != NFS_UNSTABLE || resp->verf->committed == NFS_FILE_SYNC) { nfs_inode_remove_request(req); dprintk(" OK\n"); @@ -1101,7 +1101,7 @@ nfs_writeback_done(struct rpc_task *task) } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /* * Set up the argument/result storage required for the RPC call. */ @@ -1265,7 +1265,7 @@ int nfs_flush_file(struct inode *inode, struct file *file, unsigned long idx_sta return res; } -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_start, unsigned int npages, int how) { @@ -1302,7 +1302,7 @@ int nfs_sync_file(struct inode *inode, struct file *file, unsigned long idx_star error = nfs_wait_on_requests(inode, file, idx_start, npages); if (error == 0) error = nfs_flush_file(inode, file, idx_start, npages, how); -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (error == 0) error = nfs_commit_file(inode, file, idx_start, npages, how); #endif diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index b06a0c254838..a53ad5ea4ceb 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -330,7 +330,7 @@ extern int nfs_flush_file(struct inode *, struct file *, unsigned long, unsigne extern int nfs_flush_list(struct list_head *, int, int); extern int nfs_scan_lru_dirty(struct nfs_server *, struct list_head *); extern int nfs_scan_lru_dirty_timeout(struct nfs_server *, struct list_head *); -#ifdef CONFIG_NFS_V3 +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) extern int nfs_commit_file(struct inode *, struct file *, unsigned long, unsigned int, int); extern int nfs_commit_list(struct list_head *, int); extern int nfs_scan_lru_commit(struct nfs_server *, struct list_head *); -- cgit v1.2.3 From 40a4b2a4836023d76b652f1fd695c1c6d4d63632 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:46:48 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x This patch changes the interface of the ->readdir() nfs_rpc_op so that its first argument is a dentry instead of an inode. [Explanation: The dentry is required because in NFSv4, we need to make use of the _parent_ directory's inode. This is because NFSv4 servers no longer return an entry for ".." in the READDIR response, so the client kernel needs to fake this entry, inode number and all.] --- fs/nfs/dir.c | 4 ++-- fs/nfs/nfs3proc.c | 3 ++- fs/nfs/proc.c | 3 ++- include/linux/nfs_xdr.h | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 5bb31a8ee6f0..b2540bfc295c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -107,7 +107,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index); again: - error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, page, + error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page, NFS_SERVER(inode)->dtsize, desc->plus); if (error < 0) { /* We requested READDIRPLUS, but the server doesn't grok it */ @@ -341,7 +341,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, status = -ENOMEM; goto out; } - desc->error = NFS_PROTO(inode)->readdir(inode, cred, desc->target, + desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target, page, NFS_SERVER(inode)->dtsize, desc->plus); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c14a6624179a..c0d8be017f80 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -543,9 +543,10 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name) * readdirplus. */ static int -nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred, +nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page *page, unsigned int count, int plus) { + struct inode *dir = dentry->d_inode; struct nfs_fattr dir_attr; u32 *verf = NFS_COOKIEVERF(dir); struct nfs3_readdirargs arg = { diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 51d8dba0a94f..411461013124 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -425,9 +425,10 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name) * from nfs_readdir by calling the decode_entry function directly. */ static int -nfs_proc_readdir(struct inode *dir, struct rpc_cred *cred, +nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page *page, unsigned int count, int plus) { + struct inode *dir = dentry->d_inode; struct nfs_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 8d9c04899d65..b27525074317 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -338,7 +338,7 @@ struct nfs_rpc_ops { int (*mkdir) (struct inode *, struct qstr *, struct iattr *, struct nfs_fh *, struct nfs_fattr *); int (*rmdir) (struct inode *, struct qstr *); - int (*readdir) (struct inode *, struct rpc_cred *, + int (*readdir) (struct dentry *, struct rpc_cred *, u64, struct page *, unsigned int, int); int (*mknod) (struct inode *, struct qstr *, struct iattr *, dev_t, struct nfs_fh *, struct nfs_fattr *); -- cgit v1.2.3 From 62d86355a150657b217f03a0617a757962a6fde9 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:47:02 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x This patch changes the interface of the ->setattr() nfs_rpc_op so that its first argument is a dentry instead of an inode. [Explanation: The dentry is required because in NFSv4, we may need to OPEN the file before doing the SETATTR. (This is required if the file size is changed as part of the setattr.) Opening the file requires making use of the containing directory's inode.] --- fs/nfs/inode.c | 2 +- fs/nfs/nfs3proc.c | 3 ++- fs/nfs/proc.c | 3 ++- include/linux/nfs_xdr.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 9b3329c2064f..c3f915274169 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -781,7 +781,7 @@ printk("nfs_setattr: revalidate failed, error=%d\n", error); if (error) goto out; - error = NFS_PROTO(inode)->setattr(inode, &fattr, attr); + error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); if (error) goto out; /* diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c0d8be017f80..980c97043a9f 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -86,9 +86,10 @@ nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr) } static int -nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr, +nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, struct iattr *sattr) { + struct inode *inode = dentry->d_inode; struct nfs3_sattrargs arg = { .fh = NFS_FH(inode), .sattr = sattr, diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 411461013124..9c8e22151160 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -78,9 +78,10 @@ nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr) } static int -nfs_proc_setattr(struct inode *inode, struct nfs_fattr *fattr, +nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, struct iattr *sattr) { + struct inode *inode = dentry->d_inode; struct nfs_sattrargs arg = { .fh = NFS_FH(inode), .sattr = sattr diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index b27525074317..5f6b8b84e37f 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -307,7 +307,7 @@ struct nfs_rpc_ops { int (*getroot) (struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); int (*getattr) (struct inode *, struct nfs_fattr *); - int (*setattr) (struct inode *, struct nfs_fattr *, + int (*setattr) (struct dentry *, struct nfs_fattr *, struct iattr *); int (*lookup) (struct inode *, struct qstr *, struct nfs_fh *, struct nfs_fattr *); -- cgit v1.2.3 From 61e6f97593d43b8d2a5106f0b4d8527c3b4407b4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:48:08 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x In NFSv4, an fsid is a 64-bit major number together with a 64-bit minor number. In previous versions, an fsid is a single number. This patch changes 'struct nfs_fattr' accordingly. --- fs/nfs/nfs2xdr.c | 2 +- fs/nfs/nfs3xdr.c | 2 +- include/linux/nfs_xdr.h | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index cfe936d464bd..8dc92b8b3a1c 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -107,7 +107,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) fattr->du.nfs2.blocksize = ntohl(*p++); fattr->rdev = ntohl(*p++); fattr->du.nfs2.blocks = ntohl(*p++); - fattr->fsid = ntohl(*p++); + fattr->fsid_u.nfs3 = ntohl(*p++); fattr->fileid = ntohl(*p++); p = xdr_decode_time(p, &fattr->atime); p = xdr_decode_time(p, &fattr->mtime); diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 8bc33398c498..b0c77b19fff9 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -173,7 +173,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) /* Turn remote device info into Linux-specific dev_t */ fattr->rdev = ntohl(*p++) << MINORBITS; fattr->rdev |= ntohl(*p++) & MINORMASK; - p = xdr_decode_hyper(p, &fattr->fsid); + p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3); p = xdr_decode_hyper(p, &fattr->fileid); p = xdr_decode_time3(p, &fattr->atime); p = xdr_decode_time3(p, &fattr->mtime); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 5f6b8b84e37f..ce871934f6e5 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -24,7 +24,13 @@ struct nfs_fattr { } nfs3; } du; __u32 rdev; - __u64 fsid; + union { + __u64 nfs3; /* also nfs2 */ + struct { + __u64 major; + __u64 minor; + } nfs4; + } fsid_u; __u64 fileid; __u64 atime; __u64 mtime; -- cgit v1.2.3 From 3aeba06461c3337fde1ad1009f172fcbb1edf402 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:48:22 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x This is a nontrivial change to the NFS client. NFSv4 defines a new file attribute, change_attr. This is a per-file opaque quantity returned by the server, whose value is required to change whenever the file is modified. If it exists, we want to use it for all cache consistency checks in nfs_refresh_inode(). Some operations also return a "pre-operation" value of the change_attr; we want to take this into account too. First, define flags NFS_ATTR_FATTR_V4 - indicates that the 'struct nfs_fattr' is an NFSv4 fattr, so the change_attr field is valid NFS_ATTR_PRE_CHANGE - indicates that the server returned a pre-operation change_attr, so the pre_change_attr field is valid Second, change nfs_refresh_inode() so that the caches are invalidated if there is a change_attr mismatch. Exception: If the pre_change_attr tells us that the mismatch was caused by our operation, then do not invalidate the caches. This patch should leave the logic in nfs_refresh_inode() unchanged if neither of the new flags are set. --- fs/nfs/inode.c | 20 +++++++++++++++++++- include/linux/nfs_fs.h | 2 ++ include/linux/nfs_xdr.h | 4 ++++ 3 files changed, 25 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c3f915274169..b1ba7f9211f9 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -716,6 +716,8 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) inode->i_mtime = nfs_time_to_secs(new_mtime); NFS_MTIME_UPDATE(inode) = fattr->timestamp; NFS_CACHE_ISIZE(inode) = new_size; + if (fattr->valid & NFS_ATTR_FATTR_V4) + NFS_CHANGE_ATTR(inode) = fattr->change_attr; inode->i_size = new_isize; inode->i_mode = fattr->mode; inode->i_nlink = fattr->nlink; @@ -1067,12 +1069,25 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) invalid = 1; } + if ((fattr->valid & NFS_ATTR_FATTR_V4) + && NFS_CHANGE_ATTR(inode) != fattr->change_attr) { +#ifdef NFS_DEBUG_VERBOSE + printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n", + inode->i_sb->s_id, inode->i_ino); +#endif + invalid = 1; + } + /* Check Weak Cache Consistency data. * If size and mtime match the pre-operation values, we can * assume that any attribute changes were caused by our NFS * operation, so there's no need to invalidate the caches. */ - if ((fattr->valid & NFS_ATTR_WCC) + if ((fattr->valid & NFS_ATTR_PRE_CHANGE) + && NFS_CHANGE_ATTR(inode) == fattr->pre_change_attr) { + invalid = 0; + } + else if ((fattr->valid & NFS_ATTR_WCC) && NFS_CACHE_ISIZE(inode) == fattr->pre_size && NFS_CACHE_MTIME(inode) == fattr->pre_mtime) { invalid = 0; @@ -1110,6 +1125,9 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) } } + if (fattr->valid & NFS_ATTR_FATTR_V4) + NFS_CHANGE_ATTR(inode) = fattr->change_attr; + inode->i_mode = fattr->mode; inode->i_nlink = fattr->nlink; inode->i_uid = fattr->uid; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index a53ad5ea4ceb..588cb1437080 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -144,6 +144,7 @@ struct nfs_inode { __u64 read_cache_isize; unsigned long attrtimeo; unsigned long attrtimeo_timestamp; + __u64 change_attr; /* v4 only */ /* * Timestamp that dates the change made to read_cache_mtime. @@ -208,6 +209,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode) #define NFS_CACHE_CTIME(inode) (NFS_I(inode)->read_cache_ctime) #define NFS_CACHE_MTIME(inode) (NFS_I(inode)->read_cache_mtime) #define NFS_CACHE_ISIZE(inode) (NFS_I(inode)->read_cache_isize) +#define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr) #define NFS_NEXTSCAN(inode) (NFS_I(inode)->nextscan) #define NFS_CACHEINV(inode) \ do { \ diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index ce871934f6e5..18c44a22b3d8 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -35,12 +35,16 @@ struct nfs_fattr { __u64 atime; __u64 mtime; __u64 ctime; + __u64 change_attr; /* NFSv4 change attribute */ + __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ unsigned long timestamp; }; #define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ #define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ #define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ +#define NFS_ATTR_FATTR_V4 0x0008 +#define NFS_ATTR_PRE_CHANGE 0x0010 /* * Info on the file system -- cgit v1.2.3 From 63a5ba4276af966c01116ac1e14e82be66f1f133 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:49:40 -0700 Subject: [PATCH] A basic NFSv4 client for 2.5.x This is a nontrivial change to the NFS client. In this patch, we finish modifying the async READ path so that it is version-agnostic. We define a new nfs_rpc_op ->setup_read(), and move the v2- and v3-specific code in nfs_read_rpcsetup() there. We also have to change nfs_readpage() result so that the 'count' of bytes read is a parameter. The extra parameter means that it can no longer be ->tk_exit(). Instead, it is called from a version-specific ->tk_exit() routine which is set in ->read_setup(). The upshot of all this is that the version-specific part of the async READ path has been encapsulated in a new nfs_rpc_op ->read_setup(), and NFSv4 can share the logic for asynchronous READ's with NFSv2 and v3. --- fs/nfs/nfs3proc.c | 47 ++++++++++++++++++++++++ fs/nfs/proc.c | 44 ++++++++++++++++++++++ fs/nfs/read.c | 97 +++++++++---------------------------------------- include/linux/nfs_fs.h | 7 ++++ include/linux/nfs_xdr.h | 19 ++++++++++ 5 files changed, 134 insertions(+), 80 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 980c97043a9f..4070fdc5e844 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #define NFSDBG_FACILITY NFSDBG_PROC @@ -646,6 +647,51 @@ error: extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); +static void +nfs3_read_done(struct rpc_task *task) +{ + struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; + + if (nfs_async_handle_jukebox(task)) + return; + nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof); +} + +static void +nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count) +{ + struct rpc_task *task = &data->task; + struct inode *inode = data->inode; + struct nfs_page *req; + int flags; + struct rpc_message msg; + + req = nfs_list_entry(data->pages.next); + data->u.v3.args.fh = NFS_FH(inode); + data->u.v3.args.offset = req_offset(req) + req->wb_offset; + data->u.v3.args.pgbase = req->wb_offset; + data->u.v3.args.pages = data->pagevec; + data->u.v3.args.count = count; + data->u.v3.res.fattr = &data->fattr; + data->u.v3.res.count = count; + data->u.v3.res.eof = 0; + + /* N.B. Do we need to test? Never called for swapfile inode */ + flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); + + /* Finalize the task. */ + rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags); + task->tk_calldata = data; + /* Release requests */ + task->tk_release = nfs_readdata_release; + + msg.rpc_proc = NFS3PROC_READ; + msg.rpc_argp = &data->u.v3.args; + msg.rpc_resp = &data->u.v3.res; + msg.rpc_cred = data->cred; + rpc_call_setup(&data->task, &msg, 0); +} + struct nfs_rpc_ops nfs_v3_clientops = { .version = 3, /* protocol version */ .getroot = nfs3_proc_get_root, @@ -669,4 +715,5 @@ struct nfs_rpc_ops nfs_v3_clientops = { .mknod = nfs3_proc_mknod, .statfs = nfs3_proc_statfs, .decode_dirent = nfs3_decode_dirent, + .read_setup = nfs3_proc_read_setup, }; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 9c8e22151160..2aca80f409a4 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #define NFSDBG_FACILITY NFSDBG_PROC @@ -469,6 +470,48 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); +static void +nfs_read_done(struct rpc_task *task) +{ + struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; + nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof); +} + +static void +nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count) +{ + struct rpc_task *task = &data->task; + struct inode *inode = data->inode; + struct nfs_page *req; + int flags; + struct rpc_message msg; + + req = nfs_list_entry(data->pages.next); + data->u.v3.args.fh = NFS_FH(inode); + data->u.v3.args.offset = req_offset(req) + req->wb_offset; + data->u.v3.args.pgbase = req->wb_offset; + data->u.v3.args.pages = data->pagevec; + data->u.v3.args.count = count; + data->u.v3.res.fattr = &data->fattr; + data->u.v3.res.count = count; + data->u.v3.res.eof = 0; + + /* N.B. Do we need to test? Never called for swapfile inode */ + flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); + + /* Finalize the task. */ + rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags); + task->tk_calldata = data; + /* Release requests */ + task->tk_release = nfs_readdata_release; + + msg.rpc_proc = NFSPROC_READ; + msg.rpc_argp = &data->u.v3.args; + msg.rpc_resp = &data->u.v3.res; + msg.rpc_cred = data->cred; + rpc_call_setup(&data->task, &msg, 0); +} + struct nfs_rpc_ops nfs_v2_clientops = { .version = 2, /* protocol version */ .getroot = nfs_proc_get_root, @@ -493,4 +536,5 @@ struct nfs_rpc_ops nfs_v2_clientops = { .mknod = nfs_proc_mknod, .statfs = nfs_proc_statfs, .decode_dirent = nfs_decode_dirent, + .read_setup = nfs_proc_read_setup, }; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 540ebd4a4753..867416b2df30 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -34,34 +34,6 @@ #define NFSDBG_FACILITY NFSDBG_PAGECACHE -struct nfs_read_data { - struct rpc_task task; - struct inode *inode; - struct rpc_cred *cred; - struct nfs_fattr fattr; /* fattr storage */ - struct list_head pages; /* Coalesced read requests */ - struct page *pagevec[NFS_READ_MAXIOV]; - union { - struct { - struct nfs_readargs args; - struct nfs_readres res; - } v3; /* also v2 */ -#ifdef CONFIG_NFS_V4 - /* NFSv4 data will come here... */ -#endif - } u; -}; - -/* - * Local function declarations - */ -static void nfs_readpage_result(struct rpc_task *task); - -/* Hack for future NFS swap support */ -#ifndef IS_SWAPFILE -# define IS_SWAPFILE(inode) (0) -#endif - static kmem_cache_t *nfs_rdata_cachep; static __inline__ struct nfs_read_data *nfs_readdata_alloc(void) @@ -71,7 +43,6 @@ static __inline__ struct nfs_read_data *nfs_readdata_alloc(void) if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); - p->u.v3.args.pages = p->pagevec; } return p; } @@ -81,7 +52,7 @@ static __inline__ void nfs_readdata_free(struct nfs_read_data *p) kmem_cache_free(nfs_rdata_cachep, p); } -static void nfs_readdata_release(struct rpc_task *task) +void nfs_readdata_release(struct rpc_task *task) { struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata; nfs_readdata_free(data); @@ -197,31 +168,32 @@ nfs_readpage_async(struct file *file, struct inode *inode, struct page *page) static void nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data) { - struct nfs_readargs *args = &data->u.v3.args; - struct nfs_readres *res = &data->u.v3.res; + struct inode *inode; struct nfs_page *req; struct page **pages; unsigned int count; - pages = &args->pages[0]; + pages = data->pagevec; count = 0; while (!list_empty(head)) { - struct nfs_page *req = nfs_list_entry(head->next); + req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &data->pages); *pages++ = req->wb_page; count += req->wb_bytes; } req = nfs_list_entry(data->pages.next); - data->inode = req->wb_inode; + data->inode = inode = req->wb_inode; data->cred = req->wb_cred; - args->fh = NFS_FH(req->wb_inode); - args->offset = req_offset(req) + req->wb_offset; - args->pgbase = req->wb_offset; - args->count = count; - res->fattr = &data->fattr; - res->count = count; - res->eof = 0; + + NFS_PROTO(inode)->read_setup(data, count); + + dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu.\n", + data->task.tk_pid, + inode->i_sb->s_id, + (long long)NFS_FILEID(inode), + count, + (unsigned long long)req_offset(req) + req->wb_offset); } static void @@ -245,50 +217,20 @@ nfs_async_read_error(struct list_head *head) static int nfs_pagein_one(struct list_head *head, struct inode *inode) { - struct rpc_task *task; struct rpc_clnt *clnt = NFS_CLIENT(inode); struct nfs_read_data *data; - struct rpc_message msg; - int flags; sigset_t oldset; data = nfs_readdata_alloc(); if (!data) goto out_bad; - task = &data->task; - - /* N.B. Do we need to test? Never called for swapfile inode */ - flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); nfs_read_rpcsetup(head, data); - /* Finalize the task. */ - rpc_init_task(task, clnt, nfs_readpage_result, flags); - task->tk_calldata = data; - /* Release requests */ - task->tk_release = nfs_readdata_release; - -#ifdef CONFIG_NFS_V3 - msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ? NFS3PROC_READ : NFSPROC_READ; -#else - msg.rpc_proc = NFSPROC_READ; -#endif - msg.rpc_argp = &data->u.v3.args; - msg.rpc_resp = &data->u.v3.res; - msg.rpc_cred = data->cred; - /* Start the async call */ - dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu.\n", - task->tk_pid, - inode->i_sb->s_id, - (long long)NFS_FILEID(inode), - (unsigned int)data->u.v3.args.count, - (unsigned long long)data->u.v3.args.offset); - rpc_clnt_sigmask(clnt, &oldset); - rpc_call_setup(task, &msg, 0); lock_kernel(); - rpc_execute(task); + rpc_execute(&data->task); unlock_kernel(); rpc_clnt_sigunmask(clnt, &oldset); return 0; @@ -408,20 +350,15 @@ int nfs_pagein_inode(struct inode *inode, unsigned long idx_start, * This is the callback from RPC telling us whether a reply was * received or some error occurred (timeout or socket shutdown). */ -static void -nfs_readpage_result(struct rpc_task *task) +void +nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof) { struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct inode *inode = data->inode; - unsigned int count = data->u.v3.res.count; - int eof = data->u.v3.res.eof; dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", task->tk_pid, task->tk_status); - if (nfs_async_handle_jukebox(task)) - return; - nfs_refresh_inode(inode, &data->fattr); while (!list_empty(&data->pages)) { struct nfs_page *req = nfs_list_entry(data->pages.next); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 588cb1437080..c352fcbc956d 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -379,6 +379,11 @@ nfs_wb_file(struct inode *inode, struct file *file) return (error < 0) ? error : 0; } +/* Hack for future NFS swap support */ +#ifndef IS_SWAPFILE +# define IS_SWAPFILE(inode) (0) +#endif + /* * linux/fs/nfs/read.c */ @@ -387,6 +392,8 @@ extern int nfs_pagein_inode(struct inode *, unsigned long, unsigned int); extern int nfs_pagein_list(struct list_head *, int); extern int nfs_scan_lru_read(struct nfs_server *, struct list_head *); extern int nfs_scan_lru_read_timeout(struct nfs_server *, struct list_head *); +extern void nfs_readpage_result(struct rpc_task *, unsigned int count, int eof); +extern void nfs_readdata_release(struct rpc_task *); /* * linux/fs/mount_clnt.c diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 18c44a22b3d8..eb65418342d2 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -308,6 +308,24 @@ struct nfs3_readdirres { int plus; }; +struct nfs_read_data { + struct rpc_task task; + struct inode *inode; + struct rpc_cred *cred; + struct nfs_fattr fattr; /* fattr storage */ + struct list_head pages; /* Coalesced read requests */ + struct page *pagevec[NFS_READ_MAXIOV]; + union { + struct { + struct nfs_readargs args; + struct nfs_readres res; + } v3; /* also v2 */ +#ifdef CONFIG_NFS_V4 + /* NFSv4 data will come here... */ +#endif + } u; +}; + /* * RPC procedure vector for NFSv2/NFSv3 demuxing */ @@ -355,6 +373,7 @@ struct nfs_rpc_ops { int (*statfs) (struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); + void (*read_setup) (struct nfs_read_data *, unsigned int count); }; /* -- cgit v1.2.3 From 23288376f61ebead762d32466456be114030f3cf Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 9 Oct 2002 22:50:19 -0700 Subject: [PATCH] Fix NFS locking over TCP The 2.5.x RPC code is currently broken in that it demands that all tasks that call xprt_create_proto() in order to open a TCP socket must have CAP_NET_BIND_SERVICE capabilities, and must bind to a privileged port. This breaks the NLM locking code and its use of the call_bind() RPC portmapper lookup feature. This patch allows the built-in portmapper client to use unbound TCP sockets if the user does not have the necessary capabilities. --- include/linux/sunrpc/xprt.h | 1 + net/sunrpc/xprt.c | 40 ++++++++++++++++++---------------------- 2 files changed, 19 insertions(+), 22 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index baaa8c748bbb..25b1694d6fe8 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -146,6 +146,7 @@ struct rpc_xprt { unsigned long sockstate; /* Socket state */ unsigned char shutdown : 1, /* being shut down */ nocong : 1, /* no congestion control */ + resvport : 1, /* use a reserved port */ stream : 1; /* TCP */ /* diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 7f7e9e2149d8..52ecab8632de 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -89,7 +89,7 @@ static void xprt_disconnect(struct rpc_xprt *); static void xprt_conn_status(struct rpc_task *task); static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to); -static struct socket *xprt_create_socket(int, struct rpc_timeout *); +static struct socket *xprt_create_socket(int, struct rpc_timeout *, int); static void xprt_bind_socket(struct rpc_xprt *, struct socket *); static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); @@ -442,7 +442,7 @@ xprt_connect(struct rpc_task *task) * Start by resetting any existing state. */ xprt_close(xprt); - if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout))) { + if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout, xprt->resvport))) { /* couldn't create socket or bind to reserved port; * this is likely a permanent error, so cause an abort */ task->tk_status = -EIO; @@ -1490,7 +1490,7 @@ xprt_sock_setbufsize(struct rpc_xprt *xprt) * and connect stream sockets. */ static struct socket * -xprt_create_socket(int proto, struct rpc_timeout *to) +xprt_create_socket(int proto, struct rpc_timeout *to, int resvport) { struct socket *sock; int type, err; @@ -1506,7 +1506,7 @@ xprt_create_socket(int proto, struct rpc_timeout *to) } /* If the caller has the capability, bind to a reserved port */ - if (capable(CAP_NET_BIND_SERVICE) && xprt_bindresvport(sock) < 0) { + if (resvport && xprt_bindresvport(sock) < 0) { printk("RPC: can't bind to reserved port.\n"); goto failed; } @@ -1528,29 +1528,25 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to) xprt = xprt_setup(proto, sap, to); if (!xprt) - goto out; + goto out_bad; + xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; if (!xprt->stream) { - struct socket *sock = xprt_create_socket(proto, to); - if (sock) - xprt_bind_socket(xprt, sock); - else { - rpc_free(xprt); - xprt = NULL; - } - } else - /* - * Don't allow a TCP service user unless they have - * enough capability to bind a reserved port. - */ - if (!capable(CAP_NET_BIND_SERVICE)) { - rpc_free(xprt); - xprt = NULL; - } + struct socket *sock; + + sock = xprt_create_socket(proto, to, xprt->resvport); + if (!sock) + goto out_bad; + xprt_bind_socket(xprt, sock); + } - out: dprintk("RPC: xprt_create_proto created xprt %p\n", xprt); return xprt; + out_bad: + dprintk("RPC: xprt_create_proto failed\n"); + if (xprt) + rpc_free(xprt); + return NULL; } /* -- cgit v1.2.3