Merge branch 'for-3.1' of git://linux-nfs.org/~bfields/linux
* 'for-3.1' of git://linux-nfs.org/~bfields/linux: nfsd: don't break lease on CLAIM_DELEGATE_CUR locks: rename lock-manager ops nfsd4: update nfsv4.1 implementation notes nfsd: turn on reply cache for NFSv4 nfsd4: call nfsd4_release_compoundargs from pc_release nfsd41: Deny new lock before RECLAIM_COMPLETE done fs: locks: remove init_once nfsd41: check the size of request nfsd41: error out when client sets maxreq_sz or maxresp_sz too small nfsd4: fix file leak on open_downgrade nfsd4: remember to put RW access on stateid destruction NFSD: Added TEST_STATEID operation NFSD: added FREE_STATEID operation svcrpc: fix list-corrupting race on nfsd shutdown rpc: allow autoloading of gss mechanisms svcauth_unix.c: quiet sparse noise svcsock.c: include sunrpc.h to quiet sparse noise nfsd: Remove deprecated nfsctl system call and related code. NFSD: allow OP_DESTROY_CLIENTID to be only op in COMPOUND Fix up trivial conflicts in Documentation/feature-removal-schedule.txt
This commit is contained in:
		
				commit
				
					
						2dad3206db
					
				
			
		
					 33 changed files with 559 additions and 1426 deletions
				
			
		| 
						 | 
					@ -491,16 +491,6 @@ Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
----------------------------
 | 
					----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:   access to nfsd auth cache through sys_nfsservctl or '.' files
 | 
					 | 
				
			||||||
        in the 'nfsd' filesystem.
 | 
					 | 
				
			||||||
When:   3.0
 | 
					 | 
				
			||||||
Why:    This is a legacy interface which have been replaced by a more
 | 
					 | 
				
			||||||
        dynamic cache.  Continuing to maintain this interface is an
 | 
					 | 
				
			||||||
        unnecessary burden.
 | 
					 | 
				
			||||||
Who:    NeilBrown <neilb@suse.de>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
----------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
What:	Legacy, non-standard chassis intrusion detection interface.
 | 
					What:	Legacy, non-standard chassis intrusion detection interface.
 | 
				
			||||||
When:	June 2011
 | 
					When:	June 2011
 | 
				
			||||||
Why:	The adm9240, w83792d and w83793 hardware monitoring drivers have
 | 
					Why:	The adm9240, w83792d and w83793 hardware monitoring drivers have
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -338,21 +338,21 @@ fl_release_private:	maybe		no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
----------------------- lock_manager_operations ---------------------------
 | 
					----------------------- lock_manager_operations ---------------------------
 | 
				
			||||||
prototypes:
 | 
					prototypes:
 | 
				
			||||||
	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
 | 
						int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
 | 
				
			||||||
	void (*fl_notify)(struct file_lock *);  /* unblock callback */
 | 
						void (*lm_notify)(struct file_lock *);  /* unblock callback */
 | 
				
			||||||
	int (*fl_grant)(struct file_lock *, struct file_lock *, int);
 | 
						int (*lm_grant)(struct file_lock *, struct file_lock *, int);
 | 
				
			||||||
	void (*fl_release_private)(struct file_lock *);
 | 
						void (*lm_release_private)(struct file_lock *);
 | 
				
			||||||
	void (*fl_break)(struct file_lock *); /* break_lease callback */
 | 
						void (*lm_break)(struct file_lock *); /* break_lease callback */
 | 
				
			||||||
	int (*fl_change)(struct file_lock **, int);
 | 
						int (*lm_change)(struct file_lock **, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
locking rules:
 | 
					locking rules:
 | 
				
			||||||
			file_lock_lock	may block
 | 
								file_lock_lock	may block
 | 
				
			||||||
fl_compare_owner:	yes		no
 | 
					lm_compare_owner:	yes		no
 | 
				
			||||||
fl_notify:		yes		no
 | 
					lm_notify:		yes		no
 | 
				
			||||||
fl_grant:		no		no
 | 
					lm_grant:		no		no
 | 
				
			||||||
fl_release_private:	maybe		no
 | 
					lm_release_private:	maybe		no
 | 
				
			||||||
fl_break:		yes		no
 | 
					lm_break:		yes		no
 | 
				
			||||||
fl_change		yes		no
 | 
					lm_change		yes		no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--------------------------- buffer_head -----------------------------------
 | 
					--------------------------- buffer_head -----------------------------------
 | 
				
			||||||
prototypes:
 | 
					prototypes:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,27 +39,17 @@ interoperability problems with future clients.  Known issues:
 | 
				
			||||||
	  from a linux client are possible, but we aren't really
 | 
						  from a linux client are possible, but we aren't really
 | 
				
			||||||
	  conformant with the spec (for example, we don't use kerberos
 | 
						  conformant with the spec (for example, we don't use kerberos
 | 
				
			||||||
	  on the backchannel correctly).
 | 
						  on the backchannel correctly).
 | 
				
			||||||
	- no trunking support: no clients currently take advantage of
 | 
					 | 
				
			||||||
	  trunking, but this is a mandatory feature, and its use is
 | 
					 | 
				
			||||||
	  recommended to clients in a number of places.  (E.g. to ensure
 | 
					 | 
				
			||||||
	  timely renewal in case an existing connection's retry timeouts
 | 
					 | 
				
			||||||
	  have gotten too long; see section 8.3 of the RFC.)
 | 
					 | 
				
			||||||
	  Therefore, lack of this feature may cause future clients to
 | 
					 | 
				
			||||||
	  fail.
 | 
					 | 
				
			||||||
	- Incomplete backchannel support: incomplete backchannel gss
 | 
						- Incomplete backchannel support: incomplete backchannel gss
 | 
				
			||||||
	  support and no support for BACKCHANNEL_CTL mean that
 | 
						  support and no support for BACKCHANNEL_CTL mean that
 | 
				
			||||||
	  callbacks (hence delegations and layouts) may not be
 | 
						  callbacks (hence delegations and layouts) may not be
 | 
				
			||||||
	  available and clients confused by the incomplete
 | 
						  available and clients confused by the incomplete
 | 
				
			||||||
	  implementation may fail.
 | 
						  implementation may fail.
 | 
				
			||||||
	- Server reboot recovery is unsupported; if the server reboots,
 | 
					 | 
				
			||||||
	  clients may fail.
 | 
					 | 
				
			||||||
	- We do not support SSV, which provides security for shared
 | 
						- We do not support SSV, which provides security for shared
 | 
				
			||||||
	  client-server state (thus preventing unauthorized tampering
 | 
						  client-server state (thus preventing unauthorized tampering
 | 
				
			||||||
	  with locks and opens, for example).  It is mandatory for
 | 
						  with locks and opens, for example).  It is mandatory for
 | 
				
			||||||
	  servers to support this, though no clients use it yet.
 | 
						  servers to support this, though no clients use it yet.
 | 
				
			||||||
	- Mandatory operations which we do not support, such as
 | 
						- Mandatory operations which we do not support, such as
 | 
				
			||||||
	  DESTROY_CLIENTID, FREE_STATEID, SECINFO_NO_NAME, and
 | 
						  DESTROY_CLIENTID, are not currently used by clients, but will be
 | 
				
			||||||
	  TEST_STATEID, are not currently used by clients, but will be
 | 
					 | 
				
			||||||
	  (and the spec recommends their uses in common cases), and
 | 
						  (and the spec recommends their uses in common cases), and
 | 
				
			||||||
	  clients should not be expected to know how to recover from the
 | 
						  clients should not be expected to know how to recover from the
 | 
				
			||||||
	  case where they are not supported.  This will eventually cause
 | 
						  case where they are not supported.  This will eventually cause
 | 
				
			||||||
| 
						 | 
					@ -69,8 +59,9 @@ In addition, some limitations are inherited from the current NFSv4
 | 
				
			||||||
implementation:
 | 
					implementation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	- Incomplete delegation enforcement: if a file is renamed or
 | 
						- Incomplete delegation enforcement: if a file is renamed or
 | 
				
			||||||
	  unlinked, a client holding a delegation may continue to
 | 
						  unlinked by a local process, a client holding a delegation may
 | 
				
			||||||
	  indefinitely allow opens of the file under the old name.
 | 
						  continue to indefinitely allow opens of the file under the old
 | 
				
			||||||
 | 
						  name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The table below, taken from the NFSv4.1 document, lists
 | 
					The table below, taken from the NFSv4.1 document, lists
 | 
				
			||||||
the operations that are mandatory to implement (REQ), optional
 | 
					the operations that are mandatory to implement (REQ), optional
 | 
				
			||||||
| 
						 | 
					@ -99,7 +90,7 @@ Operations
 | 
				
			||||||
   +----------------------+------------+--------------+----------------+
 | 
					   +----------------------+------------+--------------+----------------+
 | 
				
			||||||
   | ACCESS               | REQ        |              | Section 18.1   |
 | 
					   | ACCESS               | REQ        |              | Section 18.1   |
 | 
				
			||||||
NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
 | 
					NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
 | 
				
			||||||
NS | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
 | 
					I  | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
 | 
				
			||||||
   | CLOSE                | REQ        |              | Section 18.2   |
 | 
					   | CLOSE                | REQ        |              | Section 18.2   |
 | 
				
			||||||
   | COMMIT               | REQ        |              | Section 18.3   |
 | 
					   | COMMIT               | REQ        |              | Section 18.3   |
 | 
				
			||||||
   | CREATE               | REQ        |              | Section 18.4   |
 | 
					   | CREATE               | REQ        |              | Section 18.4   |
 | 
				
			||||||
| 
						 | 
					@ -111,7 +102,7 @@ NS*| DELEGPURGE           | OPT        | FDELG (REQ)  | Section 18.5   |
 | 
				
			||||||
NS | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
 | 
					NS | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
 | 
				
			||||||
I  | DESTROY_SESSION      | REQ        |              | Section 18.37  |
 | 
					I  | DESTROY_SESSION      | REQ        |              | Section 18.37  |
 | 
				
			||||||
I  | EXCHANGE_ID          | REQ        |              | Section 18.35  |
 | 
					I  | EXCHANGE_ID          | REQ        |              | Section 18.35  |
 | 
				
			||||||
NS | FREE_STATEID         | REQ        |              | Section 18.38  |
 | 
					I  | FREE_STATEID         | REQ        |              | Section 18.38  |
 | 
				
			||||||
   | GETATTR              | REQ        |              | Section 18.7   |
 | 
					   | GETATTR              | REQ        |              | Section 18.7   |
 | 
				
			||||||
P  | GETDEVICEINFO        | OPT        | pNFS (REQ)   | Section 18.40  |
 | 
					P  | GETDEVICEINFO        | OPT        | pNFS (REQ)   | Section 18.40  |
 | 
				
			||||||
P  | GETDEVICELIST        | OPT        | pNFS (OPT)   | Section 18.41  |
 | 
					P  | GETDEVICELIST        | OPT        | pNFS (OPT)   | Section 18.41  |
 | 
				
			||||||
| 
						 | 
					@ -145,14 +136,14 @@ NS*| OPENATTR             | OPT        |              | Section 18.17  |
 | 
				
			||||||
   | RESTOREFH            | REQ        |              | Section 18.27  |
 | 
					   | RESTOREFH            | REQ        |              | Section 18.27  |
 | 
				
			||||||
   | SAVEFH               | REQ        |              | Section 18.28  |
 | 
					   | SAVEFH               | REQ        |              | Section 18.28  |
 | 
				
			||||||
   | SECINFO              | REQ        |              | Section 18.29  |
 | 
					   | SECINFO              | REQ        |              | Section 18.29  |
 | 
				
			||||||
NS | SECINFO_NO_NAME      | REC        | pNFS files   | Section 18.45, |
 | 
					I  | SECINFO_NO_NAME      | REC        | pNFS files   | Section 18.45, |
 | 
				
			||||||
   |                      |            | layout (REQ) | Section 13.12  |
 | 
					   |                      |            | layout (REQ) | Section 13.12  |
 | 
				
			||||||
I  | SEQUENCE             | REQ        |              | Section 18.46  |
 | 
					I  | SEQUENCE             | REQ        |              | Section 18.46  |
 | 
				
			||||||
   | SETATTR              | REQ        |              | Section 18.30  |
 | 
					   | SETATTR              | REQ        |              | Section 18.30  |
 | 
				
			||||||
   | SETCLIENTID          | MNI        |              | N/A            |
 | 
					   | SETCLIENTID          | MNI        |              | N/A            |
 | 
				
			||||||
   | SETCLIENTID_CONFIRM  | MNI        |              | N/A            |
 | 
					   | SETCLIENTID_CONFIRM  | MNI        |              | N/A            |
 | 
				
			||||||
NS | SET_SSV              | REQ        |              | Section 18.47  |
 | 
					NS | SET_SSV              | REQ        |              | Section 18.47  |
 | 
				
			||||||
NS | TEST_STATEID         | REQ        |              | Section 18.48  |
 | 
					I  | TEST_STATEID         | REQ        |              | Section 18.48  |
 | 
				
			||||||
   | VERIFY               | REQ        |              | Section 18.31  |
 | 
					   | VERIFY               | REQ        |              | Section 18.31  |
 | 
				
			||||||
NS*| WANT_DELEGATION      | OPT        | FDELG (OPT)  | Section 18.49  |
 | 
					NS*| WANT_DELEGATION      | OPT        | FDELG (OPT)  | Section 18.49  |
 | 
				
			||||||
   | WRITE                | REQ        |              | Section 18.32  |
 | 
					   | WRITE                | REQ        |              | Section 18.32  |
 | 
				
			||||||
| 
						 | 
					@ -206,12 +197,6 @@ CREATE_SESSION:
 | 
				
			||||||
SEQUENCE:
 | 
					SEQUENCE:
 | 
				
			||||||
* no support for dynamic slot table renegotiation (optional)
 | 
					* no support for dynamic slot table renegotiation (optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nfsv4.1 COMPOUND rules:
 | 
					 | 
				
			||||||
The following cases aren't supported yet:
 | 
					 | 
				
			||||||
* Enforcing of NFS4ERR_NOT_ONLY_OP for: BIND_CONN_TO_SESSION, CREATE_SESSION,
 | 
					 | 
				
			||||||
  DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID.
 | 
					 | 
				
			||||||
* DESTROY_SESSION MUST be the final operation in the COMPOUND request.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Nonstandard compound limitations:
 | 
					Nonstandard compound limitations:
 | 
				
			||||||
* No support for a sessions fore channel RPC compound that requires both a
 | 
					* No support for a sessions fore channel RPC compound that requires both a
 | 
				
			||||||
  ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
 | 
					  ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
 | 
				
			||||||
| 
						 | 
					@ -219,3 +204,5 @@ Nonstandard compound limitations:
 | 
				
			||||||
  negotiation.
 | 
					  negotiation.
 | 
				
			||||||
* No more than one IO operation (read, write, readdir) allowed per
 | 
					* No more than one IO operation (read, write, readdir) allowed per
 | 
				
			||||||
  compound.
 | 
					  compound.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1479,7 +1479,6 @@ CONFIG_NFS_FSCACHE=y
 | 
				
			||||||
CONFIG_NFS_USE_KERNEL_DNS=y
 | 
					CONFIG_NFS_USE_KERNEL_DNS=y
 | 
				
			||||||
# CONFIG_NFS_USE_NEW_IDMAPPER is not set
 | 
					# CONFIG_NFS_USE_NEW_IDMAPPER is not set
 | 
				
			||||||
CONFIG_NFSD=m
 | 
					CONFIG_NFSD=m
 | 
				
			||||||
CONFIG_NFSD_DEPRECATED=y
 | 
					 | 
				
			||||||
CONFIG_NFSD_V2_ACL=y
 | 
					CONFIG_NFSD_V2_ACL=y
 | 
				
			||||||
CONFIG_NFSD_V3=y
 | 
					CONFIG_NFSD_V3=y
 | 
				
			||||||
CONFIG_NFSD_V3_ACL=y
 | 
					CONFIG_NFSD_V3_ACL=y
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,6 @@ obj-$(CONFIG_EVENTFD)		+= eventfd.o
 | 
				
			||||||
obj-$(CONFIG_AIO)               += aio.o
 | 
					obj-$(CONFIG_AIO)               += aio.o
 | 
				
			||||||
obj-$(CONFIG_FILE_LOCKING)      += locks.o
 | 
					obj-$(CONFIG_FILE_LOCKING)      += locks.o
 | 
				
			||||||
obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 | 
					obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 | 
				
			||||||
obj-$(CONFIG_NFSD_DEPRECATED)	+= nfsctl.o
 | 
					 | 
				
			||||||
obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
 | 
					obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
 | 
				
			||||||
obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
 | 
					obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
 | 
				
			||||||
obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
 | 
					obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										246
									
								
								fs/compat.c
									
										
									
									
									
								
							
							
						
						
									
										246
									
								
								fs/compat.c
									
										
									
									
									
								
							| 
						 | 
					@ -1675,256 +1675,10 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* HAVE_SET_RESTORE_SIGMASK */
 | 
					#endif /* HAVE_SET_RESTORE_SIGMASK */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
 | 
					 | 
				
			||||||
/* Stuff for NFS server syscalls... */
 | 
					 | 
				
			||||||
struct compat_nfsctl_svc {
 | 
					 | 
				
			||||||
	u16			svc32_port;
 | 
					 | 
				
			||||||
	s32			svc32_nthreads;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct compat_nfsctl_client {
 | 
					 | 
				
			||||||
	s8			cl32_ident[NFSCLNT_IDMAX+1];
 | 
					 | 
				
			||||||
	s32			cl32_naddr;
 | 
					 | 
				
			||||||
	struct in_addr		cl32_addrlist[NFSCLNT_ADDRMAX];
 | 
					 | 
				
			||||||
	s32			cl32_fhkeytype;
 | 
					 | 
				
			||||||
	s32			cl32_fhkeylen;
 | 
					 | 
				
			||||||
	u8			cl32_fhkey[NFSCLNT_KEYMAX];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct compat_nfsctl_export {
 | 
					 | 
				
			||||||
	char		ex32_client[NFSCLNT_IDMAX+1];
 | 
					 | 
				
			||||||
	char		ex32_path[NFS_MAXPATHLEN+1];
 | 
					 | 
				
			||||||
	compat_dev_t	ex32_dev;
 | 
					 | 
				
			||||||
	compat_ino_t	ex32_ino;
 | 
					 | 
				
			||||||
	compat_int_t	ex32_flags;
 | 
					 | 
				
			||||||
	__compat_uid_t	ex32_anon_uid;
 | 
					 | 
				
			||||||
	__compat_gid_t	ex32_anon_gid;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct compat_nfsctl_fdparm {
 | 
					 | 
				
			||||||
	struct sockaddr		gd32_addr;
 | 
					 | 
				
			||||||
	s8			gd32_path[NFS_MAXPATHLEN+1];
 | 
					 | 
				
			||||||
	compat_int_t		gd32_version;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct compat_nfsctl_fsparm {
 | 
					 | 
				
			||||||
	struct sockaddr		gd32_addr;
 | 
					 | 
				
			||||||
	s8			gd32_path[NFS_MAXPATHLEN+1];
 | 
					 | 
				
			||||||
	compat_int_t		gd32_maxlen;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct compat_nfsctl_arg {
 | 
					 | 
				
			||||||
	compat_int_t		ca32_version;	/* safeguard */
 | 
					 | 
				
			||||||
	union {
 | 
					 | 
				
			||||||
		struct compat_nfsctl_svc	u32_svc;
 | 
					 | 
				
			||||||
		struct compat_nfsctl_client	u32_client;
 | 
					 | 
				
			||||||
		struct compat_nfsctl_export	u32_export;
 | 
					 | 
				
			||||||
		struct compat_nfsctl_fdparm	u32_getfd;
 | 
					 | 
				
			||||||
		struct compat_nfsctl_fsparm	u32_getfs;
 | 
					 | 
				
			||||||
	} u;
 | 
					 | 
				
			||||||
#define ca32_svc	u.u32_svc
 | 
					 | 
				
			||||||
#define ca32_client	u.u32_client
 | 
					 | 
				
			||||||
#define ca32_export	u.u32_export
 | 
					 | 
				
			||||||
#define ca32_getfd	u.u32_getfd
 | 
					 | 
				
			||||||
#define ca32_getfs	u.u32_getfs
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
union compat_nfsctl_res {
 | 
					 | 
				
			||||||
	__u8			cr32_getfh[NFS_FHSIZE];
 | 
					 | 
				
			||||||
	struct knfsd_fh		cr32_getfs;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
 | 
					 | 
				
			||||||
				struct compat_nfsctl_arg __user *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
 | 
					 | 
				
			||||||
		get_user(karg->ca_version, &arg->ca32_version) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_svc.svc_nthreads,
 | 
					 | 
				
			||||||
				&arg->ca32_svc.svc32_nthreads))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
 | 
					 | 
				
			||||||
				struct compat_nfsctl_arg __user *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!access_ok(VERIFY_READ, &arg->ca32_client,
 | 
					 | 
				
			||||||
			sizeof(arg->ca32_client)) ||
 | 
					 | 
				
			||||||
		get_user(karg->ca_version, &arg->ca32_version) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_client.cl_ident[0],
 | 
					 | 
				
			||||||
				&arg->ca32_client.cl32_ident[0],
 | 
					 | 
				
			||||||
				NFSCLNT_IDMAX) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_client.cl_naddr,
 | 
					 | 
				
			||||||
				&arg->ca32_client.cl32_naddr) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_client.cl_addrlist[0],
 | 
					 | 
				
			||||||
				&arg->ca32_client.cl32_addrlist[0],
 | 
					 | 
				
			||||||
				(sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_client.cl_fhkeytype,
 | 
					 | 
				
			||||||
				&arg->ca32_client.cl32_fhkeytype) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_client.cl_fhkeylen,
 | 
					 | 
				
			||||||
				&arg->ca32_client.cl32_fhkeylen) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_client.cl_fhkey[0],
 | 
					 | 
				
			||||||
				&arg->ca32_client.cl32_fhkey[0],
 | 
					 | 
				
			||||||
				NFSCLNT_KEYMAX))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
 | 
					 | 
				
			||||||
				struct compat_nfsctl_arg __user *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!access_ok(VERIFY_READ, &arg->ca32_export,
 | 
					 | 
				
			||||||
				sizeof(arg->ca32_export)) ||
 | 
					 | 
				
			||||||
		get_user(karg->ca_version, &arg->ca32_version) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_export.ex_client[0],
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_client[0],
 | 
					 | 
				
			||||||
				NFSCLNT_IDMAX) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_export.ex_path[0],
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_path[0],
 | 
					 | 
				
			||||||
				NFS_MAXPATHLEN) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_export.ex_dev,
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_dev) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_export.ex_ino,
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_ino) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_export.ex_flags,
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_flags) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_export.ex_anon_uid,
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_anon_uid) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_export.ex_anon_gid,
 | 
					 | 
				
			||||||
				&arg->ca32_export.ex32_anon_gid))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
 | 
					 | 
				
			||||||
	SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
 | 
					 | 
				
			||||||
				struct compat_nfsctl_arg __user *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
 | 
					 | 
				
			||||||
			sizeof(arg->ca32_getfd)) ||
 | 
					 | 
				
			||||||
		get_user(karg->ca_version, &arg->ca32_version) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_getfd.gd_addr,
 | 
					 | 
				
			||||||
				&arg->ca32_getfd.gd32_addr,
 | 
					 | 
				
			||||||
				(sizeof(struct sockaddr))) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_getfd.gd_path,
 | 
					 | 
				
			||||||
				&arg->ca32_getfd.gd32_path,
 | 
					 | 
				
			||||||
				(NFS_MAXPATHLEN+1)) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_getfd.gd_version,
 | 
					 | 
				
			||||||
				&arg->ca32_getfd.gd32_version))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
 | 
					 | 
				
			||||||
				struct compat_nfsctl_arg __user *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
 | 
					 | 
				
			||||||
		get_user(karg->ca_version, &arg->ca32_version) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_getfs.gd_addr,
 | 
					 | 
				
			||||||
				&arg->ca32_getfs.gd32_addr,
 | 
					 | 
				
			||||||
				(sizeof(struct sockaddr))) ||
 | 
					 | 
				
			||||||
		__copy_from_user(&karg->ca_getfs.gd_path,
 | 
					 | 
				
			||||||
				&arg->ca32_getfs.gd32_path,
 | 
					 | 
				
			||||||
				(NFS_MAXPATHLEN+1)) ||
 | 
					 | 
				
			||||||
		__get_user(karg->ca_getfs.gd_maxlen,
 | 
					 | 
				
			||||||
				&arg->ca32_getfs.gd32_maxlen))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* This really doesn't need translations, we are only passing
 | 
					 | 
				
			||||||
 * back a union which contains opaque nfs file handle data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
 | 
					 | 
				
			||||||
				union compat_nfsctl_res __user *res)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = copy_to_user(res, kres, sizeof(*res));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (err) ? -EFAULT : 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
asmlinkage long compat_sys_nfsservctl(int cmd,
 | 
					 | 
				
			||||||
				struct compat_nfsctl_arg __user *arg,
 | 
					 | 
				
			||||||
				union compat_nfsctl_res __user *res)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_arg *karg;
 | 
					 | 
				
			||||||
	union nfsctl_res *kres;
 | 
					 | 
				
			||||||
	mm_segment_t oldfs;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	karg = kmalloc(sizeof(*karg), GFP_USER);
 | 
					 | 
				
			||||||
	kres = kmalloc(sizeof(*kres), GFP_USER);
 | 
					 | 
				
			||||||
	if(!karg || !kres) {
 | 
					 | 
				
			||||||
		err = -ENOMEM;
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(cmd) {
 | 
					 | 
				
			||||||
	case NFSCTL_SVC:
 | 
					 | 
				
			||||||
		err = compat_nfs_svc_trans(karg, arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case NFSCTL_ADDCLIENT:
 | 
					 | 
				
			||||||
		err = compat_nfs_clnt_trans(karg, arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case NFSCTL_DELCLIENT:
 | 
					 | 
				
			||||||
		err = compat_nfs_clnt_trans(karg, arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case NFSCTL_EXPORT:
 | 
					 | 
				
			||||||
	case NFSCTL_UNEXPORT:
 | 
					 | 
				
			||||||
		err = compat_nfs_exp_trans(karg, arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case NFSCTL_GETFD:
 | 
					 | 
				
			||||||
		err = compat_nfs_getfd_trans(karg, arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case NFSCTL_GETFS:
 | 
					 | 
				
			||||||
		err = compat_nfs_getfs_trans(karg, arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		err = -EINVAL;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	oldfs = get_fs();
 | 
					 | 
				
			||||||
	set_fs(KERNEL_DS);
 | 
					 | 
				
			||||||
	/* The __user pointer casts are valid because of the set_fs() */
 | 
					 | 
				
			||||||
	err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres);
 | 
					 | 
				
			||||||
	set_fs(oldfs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if((cmd == NFSCTL_GETFD) ||
 | 
					 | 
				
			||||||
	   (cmd == NFSCTL_GETFS))
 | 
					 | 
				
			||||||
		err = compat_nfs_getfh_res_trans(kres, res);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	kfree(karg);
 | 
					 | 
				
			||||||
	kfree(kres);
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#else /* !NFSD */
 | 
					 | 
				
			||||||
long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
 | 
					long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return sys_ni_syscall();
 | 
						return sys_ni_syscall();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_EPOLL
 | 
					#ifdef CONFIG_EPOLL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ static void do_unlock_close(struct dlm_ls *ls, u64 number,
 | 
				
			||||||
	op->info.number		= number;
 | 
						op->info.number		= number;
 | 
				
			||||||
	op->info.start		= 0;
 | 
						op->info.start		= 0;
 | 
				
			||||||
	op->info.end		= OFFSET_MAX;
 | 
						op->info.end		= OFFSET_MAX;
 | 
				
			||||||
	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
 | 
						if (fl->fl_lmops && fl->fl_lmops->lm_grant)
 | 
				
			||||||
		op->info.owner	= (__u64) fl->fl_pid;
 | 
							op->info.owner	= (__u64) fl->fl_pid;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		op->info.owner	= (__u64)(long) fl->fl_owner;
 | 
							op->info.owner	= (__u64)(long) fl->fl_owner;
 | 
				
			||||||
| 
						 | 
					@ -128,11 +128,11 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 | 
				
			||||||
	op->info.number		= number;
 | 
						op->info.number		= number;
 | 
				
			||||||
	op->info.start		= fl->fl_start;
 | 
						op->info.start		= fl->fl_start;
 | 
				
			||||||
	op->info.end		= fl->fl_end;
 | 
						op->info.end		= fl->fl_end;
 | 
				
			||||||
	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
 | 
						if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
 | 
				
			||||||
		/* fl_owner is lockd which doesn't distinguish
 | 
							/* fl_owner is lockd which doesn't distinguish
 | 
				
			||||||
		   processes on the nfs client */
 | 
							   processes on the nfs client */
 | 
				
			||||||
		op->info.owner	= (__u64) fl->fl_pid;
 | 
							op->info.owner	= (__u64) fl->fl_pid;
 | 
				
			||||||
		xop->callback	= fl->fl_lmops->fl_grant;
 | 
							xop->callback	= fl->fl_lmops->lm_grant;
 | 
				
			||||||
		locks_init_lock(&xop->flc);
 | 
							locks_init_lock(&xop->flc);
 | 
				
			||||||
		locks_copy_lock(&xop->flc, fl);
 | 
							locks_copy_lock(&xop->flc, fl);
 | 
				
			||||||
		xop->fl		= fl;
 | 
							xop->fl		= fl;
 | 
				
			||||||
| 
						 | 
					@ -268,7 +268,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 | 
				
			||||||
	op->info.number		= number;
 | 
						op->info.number		= number;
 | 
				
			||||||
	op->info.start		= fl->fl_start;
 | 
						op->info.start		= fl->fl_start;
 | 
				
			||||||
	op->info.end		= fl->fl_end;
 | 
						op->info.end		= fl->fl_end;
 | 
				
			||||||
	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
 | 
						if (fl->fl_lmops && fl->fl_lmops->lm_grant)
 | 
				
			||||||
		op->info.owner	= (__u64) fl->fl_pid;
 | 
							op->info.owner	= (__u64) fl->fl_pid;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		op->info.owner	= (__u64)(long) fl->fl_owner;
 | 
							op->info.owner	= (__u64)(long) fl->fl_owner;
 | 
				
			||||||
| 
						 | 
					@ -327,7 +327,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 | 
				
			||||||
	op->info.number		= number;
 | 
						op->info.number		= number;
 | 
				
			||||||
	op->info.start		= fl->fl_start;
 | 
						op->info.start		= fl->fl_start;
 | 
				
			||||||
	op->info.end		= fl->fl_end;
 | 
						op->info.end		= fl->fl_end;
 | 
				
			||||||
	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
 | 
						if (fl->fl_lmops && fl->fl_lmops->lm_grant)
 | 
				
			||||||
		op->info.owner	= (__u64) fl->fl_pid;
 | 
							op->info.owner	= (__u64) fl->fl_pid;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		op->info.owner	= (__u64)(long) fl->fl_owner;
 | 
							op->info.owner	= (__u64)(long) fl->fl_owner;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1507,7 +1507,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
 | 
				
			||||||
	pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
 | 
						pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
 | 
						if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
 | 
				
			||||||
		/* NLM needs asynchronous locks, which we don't support yet */
 | 
							/* NLM needs asynchronous locks, which we don't support yet */
 | 
				
			||||||
		return -ENOLCK;
 | 
							return -ENOLCK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -632,7 +632,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This is a callback from the filesystem for VFS file lock requests.
 | 
					 * This is a callback from the filesystem for VFS file lock requests.
 | 
				
			||||||
 * It will be used if fl_grant is defined and the filesystem can not
 | 
					 * It will be used if lm_grant is defined and the filesystem can not
 | 
				
			||||||
 * respond to the request immediately.
 | 
					 * respond to the request immediately.
 | 
				
			||||||
 * For GETLK request it will copy the reply to the nlm_block.
 | 
					 * For GETLK request it will copy the reply to the nlm_block.
 | 
				
			||||||
 * For SETLK or SETLKW request it will get the local posix lock.
 | 
					 * For SETLK or SETLKW request it will get the local posix lock.
 | 
				
			||||||
| 
						 | 
					@ -719,9 +719,9 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct lock_manager_operations nlmsvc_lock_operations = {
 | 
					const struct lock_manager_operations nlmsvc_lock_operations = {
 | 
				
			||||||
	.fl_compare_owner = nlmsvc_same_owner,
 | 
						.lm_compare_owner = nlmsvc_same_owner,
 | 
				
			||||||
	.fl_notify = nlmsvc_notify_blocked,
 | 
						.lm_notify = nlmsvc_notify_blocked,
 | 
				
			||||||
	.fl_grant = nlmsvc_grant_deferred,
 | 
						.lm_grant = nlmsvc_grant_deferred,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										75
									
								
								fs/locks.c
									
										
									
									
									
								
							
							
						
						
									
										75
									
								
								fs/locks.c
									
										
									
									
									
								
							| 
						 | 
					@ -160,26 +160,20 @@ EXPORT_SYMBOL_GPL(unlock_flocks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct kmem_cache *filelock_cache __read_mostly;
 | 
					static struct kmem_cache *filelock_cache __read_mostly;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void locks_init_lock_always(struct file_lock *fl)
 | 
					static void locks_init_lock_heads(struct file_lock *fl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	fl->fl_next = NULL;
 | 
						INIT_LIST_HEAD(&fl->fl_link);
 | 
				
			||||||
	fl->fl_fasync = NULL;
 | 
						INIT_LIST_HEAD(&fl->fl_block);
 | 
				
			||||||
	fl->fl_owner = NULL;
 | 
						init_waitqueue_head(&fl->fl_wait);
 | 
				
			||||||
	fl->fl_pid = 0;
 | 
					 | 
				
			||||||
	fl->fl_nspid = NULL;
 | 
					 | 
				
			||||||
	fl->fl_file = NULL;
 | 
					 | 
				
			||||||
	fl->fl_flags = 0;
 | 
					 | 
				
			||||||
	fl->fl_type = 0;
 | 
					 | 
				
			||||||
	fl->fl_start = fl->fl_end = 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Allocate an empty lock structure. */
 | 
					/* Allocate an empty lock structure. */
 | 
				
			||||||
struct file_lock *locks_alloc_lock(void)
 | 
					struct file_lock *locks_alloc_lock(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct file_lock *fl = kmem_cache_alloc(filelock_cache, GFP_KERNEL);
 | 
						struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fl)
 | 
						if (fl)
 | 
				
			||||||
		locks_init_lock_always(fl);
 | 
							locks_init_lock_heads(fl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return fl;
 | 
						return fl;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -193,8 +187,8 @@ void locks_release_private(struct file_lock *fl)
 | 
				
			||||||
		fl->fl_ops = NULL;
 | 
							fl->fl_ops = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (fl->fl_lmops) {
 | 
						if (fl->fl_lmops) {
 | 
				
			||||||
		if (fl->fl_lmops->fl_release_private)
 | 
							if (fl->fl_lmops->lm_release_private)
 | 
				
			||||||
			fl->fl_lmops->fl_release_private(fl);
 | 
								fl->fl_lmops->lm_release_private(fl);
 | 
				
			||||||
		fl->fl_lmops = NULL;
 | 
							fl->fl_lmops = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,27 +209,12 @@ EXPORT_SYMBOL(locks_free_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void locks_init_lock(struct file_lock *fl)
 | 
					void locks_init_lock(struct file_lock *fl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	INIT_LIST_HEAD(&fl->fl_link);
 | 
						memset(fl, 0, sizeof(struct file_lock));
 | 
				
			||||||
	INIT_LIST_HEAD(&fl->fl_block);
 | 
						locks_init_lock_heads(fl);
 | 
				
			||||||
	init_waitqueue_head(&fl->fl_wait);
 | 
					 | 
				
			||||||
	fl->fl_ops = NULL;
 | 
					 | 
				
			||||||
	fl->fl_lmops = NULL;
 | 
					 | 
				
			||||||
	locks_init_lock_always(fl);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPORT_SYMBOL(locks_init_lock);
 | 
					EXPORT_SYMBOL(locks_init_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Initialises the fields of the file lock which are invariant for
 | 
					 | 
				
			||||||
 * free file_locks.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void init_once(void *foo)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct file_lock *lock = (struct file_lock *) foo;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	locks_init_lock(lock);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
 | 
					static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (fl->fl_ops) {
 | 
						if (fl->fl_ops) {
 | 
				
			||||||
| 
						 | 
					@ -444,9 +423,9 @@ static void lease_release_private_callback(struct file_lock *fl)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct lock_manager_operations lease_manager_ops = {
 | 
					static const struct lock_manager_operations lease_manager_ops = {
 | 
				
			||||||
	.fl_break = lease_break_callback,
 | 
						.lm_break = lease_break_callback,
 | 
				
			||||||
	.fl_release_private = lease_release_private_callback,
 | 
						.lm_release_private = lease_release_private_callback,
 | 
				
			||||||
	.fl_change = lease_modify,
 | 
						.lm_change = lease_modify,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -499,9 +478,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 | 
					static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
 | 
						if (fl1->fl_lmops && fl1->fl_lmops->lm_compare_owner)
 | 
				
			||||||
		return fl2->fl_lmops == fl1->fl_lmops &&
 | 
							return fl2->fl_lmops == fl1->fl_lmops &&
 | 
				
			||||||
			fl1->fl_lmops->fl_compare_owner(fl1, fl2);
 | 
								fl1->fl_lmops->lm_compare_owner(fl1, fl2);
 | 
				
			||||||
	return fl1->fl_owner == fl2->fl_owner;
 | 
						return fl1->fl_owner == fl2->fl_owner;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -551,8 +530,8 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
 | 
				
			||||||
		waiter = list_first_entry(&blocker->fl_block,
 | 
							waiter = list_first_entry(&blocker->fl_block,
 | 
				
			||||||
				struct file_lock, fl_block);
 | 
									struct file_lock, fl_block);
 | 
				
			||||||
		__locks_delete_block(waiter);
 | 
							__locks_delete_block(waiter);
 | 
				
			||||||
		if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
 | 
							if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
 | 
				
			||||||
			waiter->fl_lmops->fl_notify(waiter);
 | 
								waiter->fl_lmops->lm_notify(waiter);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			wake_up(&waiter->fl_wait);
 | 
								wake_up(&waiter->fl_wait);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1239,7 +1218,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
 | 
				
			||||||
			fl->fl_type = future;
 | 
								fl->fl_type = future;
 | 
				
			||||||
			fl->fl_break_time = break_time;
 | 
								fl->fl_break_time = break_time;
 | 
				
			||||||
			/* lease must have lmops break callback */
 | 
								/* lease must have lmops break callback */
 | 
				
			||||||
			fl->fl_lmops->fl_break(fl);
 | 
								fl->fl_lmops->lm_break(fl);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1349,7 +1328,7 @@ int fcntl_getlease(struct file *filp)
 | 
				
			||||||
 *	@arg: type of lease to obtain
 | 
					 *	@arg: type of lease to obtain
 | 
				
			||||||
 *	@flp: input - file_lock to use, output - file_lock inserted
 | 
					 *	@flp: input - file_lock to use, output - file_lock inserted
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	The (input) flp->fl_lmops->fl_break function is required
 | 
					 *	The (input) flp->fl_lmops->lm_break function is required
 | 
				
			||||||
 *	by break_lease().
 | 
					 *	by break_lease().
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Called with file_lock_lock held.
 | 
					 *	Called with file_lock_lock held.
 | 
				
			||||||
| 
						 | 
					@ -1375,7 +1354,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	time_out_leases(inode);
 | 
						time_out_leases(inode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUG_ON(!(*flp)->fl_lmops->fl_break);
 | 
						BUG_ON(!(*flp)->fl_lmops->lm_break);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (arg != F_UNLCK) {
 | 
						if (arg != F_UNLCK) {
 | 
				
			||||||
		error = -EAGAIN;
 | 
							error = -EAGAIN;
 | 
				
			||||||
| 
						 | 
					@ -1417,7 +1396,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (my_before != NULL) {
 | 
						if (my_before != NULL) {
 | 
				
			||||||
		error = lease->fl_lmops->fl_change(my_before, arg);
 | 
							error = lease->fl_lmops->lm_change(my_before, arg);
 | 
				
			||||||
		if (!error)
 | 
							if (!error)
 | 
				
			||||||
			*flp = *my_before;
 | 
								*flp = *my_before;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -1453,7 +1432,7 @@ static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
 | 
				
			||||||
 *	@lease: file_lock to use
 | 
					 *	@lease: file_lock to use
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Call this to establish a lease on the file.
 | 
					 *	Call this to establish a lease on the file.
 | 
				
			||||||
 *	The (*lease)->fl_lmops->fl_break operation must be set; if not,
 | 
					 *	The (*lease)->fl_lmops->lm_break operation must be set; if not,
 | 
				
			||||||
 *	break_lease will oops!
 | 
					 *	break_lease will oops!
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	This will call the filesystem's setlease file method, if
 | 
					 *	This will call the filesystem's setlease file method, if
 | 
				
			||||||
| 
						 | 
					@ -1751,10 +1730,10 @@ out:
 | 
				
			||||||
 * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
 | 
					 * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
 | 
				
			||||||
 * locks, the ->lock() interface may return asynchronously, before the lock has
 | 
					 * locks, the ->lock() interface may return asynchronously, before the lock has
 | 
				
			||||||
 * been granted or denied by the underlying filesystem, if (and only if)
 | 
					 * been granted or denied by the underlying filesystem, if (and only if)
 | 
				
			||||||
 * fl_grant is set. Callers expecting ->lock() to return asynchronously
 | 
					 * lm_grant is set. Callers expecting ->lock() to return asynchronously
 | 
				
			||||||
 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
 | 
					 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
 | 
				
			||||||
 * the request is for a blocking lock. When ->lock() does return asynchronously,
 | 
					 * the request is for a blocking lock. When ->lock() does return asynchronously,
 | 
				
			||||||
 * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock
 | 
					 * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
 | 
				
			||||||
 * request completes.
 | 
					 * request completes.
 | 
				
			||||||
 * If the request is for non-blocking lock the file system should return
 | 
					 * If the request is for non-blocking lock the file system should return
 | 
				
			||||||
 * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
 | 
					 * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
 | 
				
			||||||
| 
						 | 
					@ -1764,7 +1743,7 @@ out:
 | 
				
			||||||
 * grants a lock so the VFS can find out which locks are locally held and do
 | 
					 * grants a lock so the VFS can find out which locks are locally held and do
 | 
				
			||||||
 * the correct lock cleanup when required.
 | 
					 * the correct lock cleanup when required.
 | 
				
			||||||
 * The underlying filesystem must not drop the kernel lock or call
 | 
					 * The underlying filesystem must not drop the kernel lock or call
 | 
				
			||||||
 * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED
 | 
					 * ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED
 | 
				
			||||||
 * return code.
 | 
					 * return code.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
 | 
					int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
 | 
				
			||||||
| 
						 | 
					@ -2333,8 +2312,8 @@ EXPORT_SYMBOL(lock_may_write);
 | 
				
			||||||
static int __init filelock_init(void)
 | 
					static int __init filelock_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	filelock_cache = kmem_cache_create("file_lock_cache",
 | 
						filelock_cache = kmem_cache_create("file_lock_cache",
 | 
				
			||||||
			sizeof(struct file_lock), 0, SLAB_PANIC,
 | 
								sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
 | 
				
			||||||
			init_once);
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										100
									
								
								fs/nfsctl.c
									
										
									
									
									
								
							
							
						
						
									
										100
									
								
								fs/nfsctl.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,100 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 *	fs/nfsctl.c
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *	This should eventually move to userland.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <linux/types.h>
 | 
					 | 
				
			||||||
#include <linux/file.h>
 | 
					 | 
				
			||||||
#include <linux/fs.h>
 | 
					 | 
				
			||||||
#include <linux/nfsd/syscall.h>
 | 
					 | 
				
			||||||
#include <linux/cred.h>
 | 
					 | 
				
			||||||
#include <linux/sched.h>
 | 
					 | 
				
			||||||
#include <linux/linkage.h>
 | 
					 | 
				
			||||||
#include <linux/namei.h>
 | 
					 | 
				
			||||||
#include <linux/mount.h>
 | 
					 | 
				
			||||||
#include <linux/syscalls.h>
 | 
					 | 
				
			||||||
#include <asm/uaccess.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * open a file on nfsd fs
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct file *do_open(char *name, int flags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct vfsmount *mnt;
 | 
					 | 
				
			||||||
	struct file *file;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
 | 
					 | 
				
			||||||
	if (IS_ERR(mnt))
 | 
					 | 
				
			||||||
		return (struct file *)mnt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	file = file_open_root(mnt->mnt_root, mnt, name, flags);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mntput(mnt);	/* drop do_kern_mount reference */
 | 
					 | 
				
			||||||
	return file;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct {
 | 
					 | 
				
			||||||
	char *name; int wsize; int rsize;
 | 
					 | 
				
			||||||
} map[] = {
 | 
					 | 
				
			||||||
	[NFSCTL_SVC] = {
 | 
					 | 
				
			||||||
		.name	= ".svc",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_svc)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	[NFSCTL_ADDCLIENT] = {
 | 
					 | 
				
			||||||
		.name	= ".add",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_client)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	[NFSCTL_DELCLIENT] = {
 | 
					 | 
				
			||||||
		.name	= ".del",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_client)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	[NFSCTL_EXPORT] = {
 | 
					 | 
				
			||||||
		.name	= ".export",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_export)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	[NFSCTL_UNEXPORT] = {
 | 
					 | 
				
			||||||
		.name	= ".unexport",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_export)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	[NFSCTL_GETFD] = {
 | 
					 | 
				
			||||||
		.name	= ".getfd",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_fdparm),
 | 
					 | 
				
			||||||
		.rsize	= NFS_FHSIZE
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	[NFSCTL_GETFS] = {
 | 
					 | 
				
			||||||
		.name	= ".getfs",
 | 
					 | 
				
			||||||
		.wsize	= sizeof(struct nfsctl_fsparm),
 | 
					 | 
				
			||||||
		.rsize	= sizeof(struct knfsd_fh)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SYSCALL_DEFINE3(nfsservctl, int, cmd, struct nfsctl_arg __user *, arg,
 | 
					 | 
				
			||||||
		void __user *, res)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct file *file;
 | 
					 | 
				
			||||||
	void __user *p = &arg->u;
 | 
					 | 
				
			||||||
	int version;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (copy_from_user(&version, &arg->ca_version, sizeof(int)))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (version != NFSCTL_VERSION)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (cmd < 0 || cmd >= ARRAY_SIZE(map) || !map[cmd].name)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	file = do_open(map[cmd].name, map[cmd].rsize ? O_RDWR : O_WRONLY);	
 | 
					 | 
				
			||||||
	if (IS_ERR(file))
 | 
					 | 
				
			||||||
		return PTR_ERR(file);
 | 
					 | 
				
			||||||
	err = file->f_op->write(file, p, map[cmd].wsize, &file->f_pos);
 | 
					 | 
				
			||||||
	if (err >= 0 && map[cmd].rsize)
 | 
					 | 
				
			||||||
		err = file->f_op->read(file, res, map[cmd].rsize, &file->f_pos);
 | 
					 | 
				
			||||||
	if (err >= 0)
 | 
					 | 
				
			||||||
		err = 0;
 | 
					 | 
				
			||||||
	fput(file);
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -28,18 +28,6 @@ config NFSD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  If unsure, say N.
 | 
						  If unsure, say N.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	bool "Include support for deprecated syscall interface to NFSD"
 | 
					 | 
				
			||||||
	depends on NFSD
 | 
					 | 
				
			||||||
	default y
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	  The syscall interface to nfsd was obsoleted in 2.6.0 by a new
 | 
					 | 
				
			||||||
	  filesystem based interface.  The old interface is due for removal
 | 
					 | 
				
			||||||
	  in 2.6.40.  If you wish to remove the interface before then
 | 
					 | 
				
			||||||
	  say N.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	  In unsure, say Y.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config NFSD_V2_ACL
 | 
					config NFSD_V2_ACL
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	depends on NFSD
 | 
						depends on NFSD
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ enum {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int	nfsd_reply_cache_init(void);
 | 
					int	nfsd_reply_cache_init(void);
 | 
				
			||||||
void	nfsd_reply_cache_shutdown(void);
 | 
					void	nfsd_reply_cache_shutdown(void);
 | 
				
			||||||
int	nfsd_cache_lookup(struct svc_rqst *, int);
 | 
					int	nfsd_cache_lookup(struct svc_rqst *);
 | 
				
			||||||
void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
 | 
					void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_V4
 | 
					#ifdef CONFIG_NFSD_V4
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										418
									
								
								fs/nfsd/export.c
									
										
									
									
									
								
							
							
						
						
									
										418
									
								
								fs/nfsd/export.c
									
										
									
									
									
								
							| 
						 | 
					@ -797,58 +797,6 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
 | 
				
			||||||
	return ek;
 | 
						return ek;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
 | 
					 | 
				
			||||||
		       struct svc_export *exp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct svc_expkey key, *ek;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	key.ek_client = clp;
 | 
					 | 
				
			||||||
	key.ek_fsidtype = fsid_type;
 | 
					 | 
				
			||||||
	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
 | 
					 | 
				
			||||||
	key.ek_path = exp->ex_path;
 | 
					 | 
				
			||||||
	key.h.expiry_time = NEVER;
 | 
					 | 
				
			||||||
	key.h.flags = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ek = svc_expkey_lookup(&key);
 | 
					 | 
				
			||||||
	if (ek)
 | 
					 | 
				
			||||||
		ek = svc_expkey_update(&key,ek);
 | 
					 | 
				
			||||||
	if (ek) {
 | 
					 | 
				
			||||||
		cache_put(&ek->h, &svc_expkey_cache);
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return -ENOMEM;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Find the client's export entry matching xdev/xino.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline struct svc_expkey *
 | 
					 | 
				
			||||||
exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	u32 fsidv[3];
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if (old_valid_dev(dev)) {
 | 
					 | 
				
			||||||
		mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
 | 
					 | 
				
			||||||
		return exp_find_key(clp, FSID_DEV, fsidv, NULL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
 | 
					 | 
				
			||||||
	return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Find the client's export entry matching fsid
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline struct svc_expkey *
 | 
					 | 
				
			||||||
exp_get_fsid_key(svc_client *clp, int fsid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	u32 fsidv[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return exp_find_key(clp, FSID_NUM, fsidv, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
 | 
					static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
 | 
				
			||||||
				     struct cache_req *reqp)
 | 
									     struct cache_req *reqp)
 | 
				
			||||||
| 
						 | 
					@ -890,275 +838,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
 | 
				
			||||||
	return exp;
 | 
						return exp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Hashtable locking. Write locks are placed only by user processes
 | 
					 | 
				
			||||||
 * wanting to modify export information.
 | 
					 | 
				
			||||||
 * Write locking only done in this file.  Read locking
 | 
					 | 
				
			||||||
 * needed externally.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static DECLARE_RWSEM(hash_sem);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
exp_readlock(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	down_read(&hash_sem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void
 | 
					 | 
				
			||||||
exp_writelock(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	down_write(&hash_sem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
exp_readunlock(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	up_read(&hash_sem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void
 | 
					 | 
				
			||||||
exp_writeunlock(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	up_write(&hash_sem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* hash_sem not needed once deprecated interface is removed */
 | 
					 | 
				
			||||||
void exp_readlock(void) {}
 | 
					 | 
				
			||||||
static inline void exp_writelock(void){}
 | 
					 | 
				
			||||||
void exp_readunlock(void) {}
 | 
					 | 
				
			||||||
static inline void exp_writeunlock(void){}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
static void		exp_do_unexport(svc_export *unexp);
 | 
					 | 
				
			||||||
static int		exp_verify_string(char *cp, int max);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void exp_fsid_unhash(struct svc_export *exp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct svc_expkey *ek;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((exp->ex_flags & NFSEXP_FSID) == 0)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
 | 
					 | 
				
			||||||
	if (!IS_ERR(ek)) {
 | 
					 | 
				
			||||||
		sunrpc_invalidate(&ek->h, &svc_expkey_cache);
 | 
					 | 
				
			||||||
		cache_put(&ek->h, &svc_expkey_cache);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	u32 fsid[2];
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
	if ((exp->ex_flags & NFSEXP_FSID) == 0)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
 | 
					 | 
				
			||||||
	return exp_set_key(clp, FSID_NUM, fsid, exp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	u32 fsid[2];
 | 
					 | 
				
			||||||
	struct inode *inode = exp->ex_path.dentry->d_inode;
 | 
					 | 
				
			||||||
	dev_t dev = inode->i_sb->s_dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (old_valid_dev(dev)) {
 | 
					 | 
				
			||||||
		mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
 | 
					 | 
				
			||||||
		return exp_set_key(clp, FSID_DEV, fsid, exp);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
 | 
					 | 
				
			||||||
	return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void exp_unhash(struct svc_export *exp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct svc_expkey *ek;
 | 
					 | 
				
			||||||
	struct inode *inode = exp->ex_path.dentry->d_inode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
 | 
					 | 
				
			||||||
	if (!IS_ERR(ek)) {
 | 
					 | 
				
			||||||
		sunrpc_invalidate(&ek->h, &svc_expkey_cache);
 | 
					 | 
				
			||||||
		cache_put(&ek->h, &svc_expkey_cache);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Export a file system.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
exp_export(struct nfsctl_export *nxp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	svc_client	*clp;
 | 
					 | 
				
			||||||
	struct svc_export	*exp = NULL;
 | 
					 | 
				
			||||||
	struct svc_export	new;
 | 
					 | 
				
			||||||
	struct svc_expkey	*fsid_key = NULL;
 | 
					 | 
				
			||||||
	struct path path;
 | 
					 | 
				
			||||||
	int		err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Consistency check */
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
	if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
 | 
					 | 
				
			||||||
	    !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
 | 
					 | 
				
			||||||
			nxp->ex_client, nxp->ex_path,
 | 
					 | 
				
			||||||
			(unsigned)nxp->ex_dev, (long)nxp->ex_ino,
 | 
					 | 
				
			||||||
			nxp->ex_flags);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Try to lock the export table for update */
 | 
					 | 
				
			||||||
	exp_writelock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Look up client info */
 | 
					 | 
				
			||||||
	if (!(clp = auth_domain_find(nxp->ex_client)))
 | 
					 | 
				
			||||||
		goto out_unlock;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Look up the dentry */
 | 
					 | 
				
			||||||
	err = kern_path(nxp->ex_path, 0, &path);
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		goto out_put_clp;
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exp = exp_get_by_name(clp, &path, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&new, 0, sizeof(new));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* must make sure there won't be an ex_fsid clash */
 | 
					 | 
				
			||||||
	if ((nxp->ex_flags & NFSEXP_FSID) &&
 | 
					 | 
				
			||||||
	    (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
 | 
					 | 
				
			||||||
	    fsid_key->ek_path.mnt &&
 | 
					 | 
				
			||||||
	    (fsid_key->ek_path.mnt != path.mnt ||
 | 
					 | 
				
			||||||
	     fsid_key->ek_path.dentry != path.dentry))
 | 
					 | 
				
			||||||
		goto finish;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!IS_ERR(exp)) {
 | 
					 | 
				
			||||||
		/* just a flags/id/fsid update */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		exp_fsid_unhash(exp);
 | 
					 | 
				
			||||||
		exp->ex_flags    = nxp->ex_flags;
 | 
					 | 
				
			||||||
		exp->ex_anon_uid = nxp->ex_anon_uid;
 | 
					 | 
				
			||||||
		exp->ex_anon_gid = nxp->ex_anon_gid;
 | 
					 | 
				
			||||||
		exp->ex_fsid     = nxp->ex_dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		err = exp_fsid_hash(clp, exp);
 | 
					 | 
				
			||||||
		goto finish;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
 | 
					 | 
				
			||||||
	if (err) goto finish;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	new.h.expiry_time = NEVER;
 | 
					 | 
				
			||||||
	new.h.flags = 0;
 | 
					 | 
				
			||||||
	new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (!new.ex_pathname)
 | 
					 | 
				
			||||||
		goto finish;
 | 
					 | 
				
			||||||
	new.ex_client = clp;
 | 
					 | 
				
			||||||
	new.ex_path = path;
 | 
					 | 
				
			||||||
	new.ex_flags = nxp->ex_flags;
 | 
					 | 
				
			||||||
	new.ex_anon_uid = nxp->ex_anon_uid;
 | 
					 | 
				
			||||||
	new.ex_anon_gid = nxp->ex_anon_gid;
 | 
					 | 
				
			||||||
	new.ex_fsid = nxp->ex_dev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exp = svc_export_lookup(&new);
 | 
					 | 
				
			||||||
	if (exp)
 | 
					 | 
				
			||||||
		exp = svc_export_update(&new, exp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!exp)
 | 
					 | 
				
			||||||
		goto finish;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (exp_hash(clp, exp) ||
 | 
					 | 
				
			||||||
	    exp_fsid_hash(clp, exp)) {
 | 
					 | 
				
			||||||
		/* failed to create at least one index */
 | 
					 | 
				
			||||||
		exp_do_unexport(exp);
 | 
					 | 
				
			||||||
		cache_flush();
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		err = 0;
 | 
					 | 
				
			||||||
finish:
 | 
					 | 
				
			||||||
	kfree(new.ex_pathname);
 | 
					 | 
				
			||||||
	if (!IS_ERR_OR_NULL(exp))
 | 
					 | 
				
			||||||
		exp_put(exp);
 | 
					 | 
				
			||||||
	if (!IS_ERR_OR_NULL(fsid_key))
 | 
					 | 
				
			||||||
		cache_put(&fsid_key->h, &svc_expkey_cache);
 | 
					 | 
				
			||||||
	path_put(&path);
 | 
					 | 
				
			||||||
out_put_clp:
 | 
					 | 
				
			||||||
	auth_domain_put(clp);
 | 
					 | 
				
			||||||
out_unlock:
 | 
					 | 
				
			||||||
	exp_writeunlock();
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Unexport a file system. The export entry has already
 | 
					 | 
				
			||||||
 * been removed from the client's list of exported fs's.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
exp_do_unexport(svc_export *unexp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	sunrpc_invalidate(&unexp->h, &svc_export_cache);
 | 
					 | 
				
			||||||
	exp_unhash(unexp);
 | 
					 | 
				
			||||||
	exp_fsid_unhash(unexp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * unexport syscall.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
exp_unexport(struct nfsctl_export *nxp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct auth_domain *dom;
 | 
					 | 
				
			||||||
	svc_export *exp;
 | 
					 | 
				
			||||||
	struct path path;
 | 
					 | 
				
			||||||
	int		err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Consistency check */
 | 
					 | 
				
			||||||
	if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
 | 
					 | 
				
			||||||
	    !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exp_writelock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
	dom = auth_domain_find(nxp->ex_client);
 | 
					 | 
				
			||||||
	if (!dom) {
 | 
					 | 
				
			||||||
		dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
 | 
					 | 
				
			||||||
		goto out_unlock;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = kern_path(nxp->ex_path, 0, &path);
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		goto out_domain;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
	exp = exp_get_by_name(dom, &path, NULL);
 | 
					 | 
				
			||||||
	path_put(&path);
 | 
					 | 
				
			||||||
	if (IS_ERR(exp))
 | 
					 | 
				
			||||||
		goto out_domain;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exp_do_unexport(exp);
 | 
					 | 
				
			||||||
	exp_put(exp);
 | 
					 | 
				
			||||||
	err = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out_domain:
 | 
					 | 
				
			||||||
	auth_domain_put(dom);
 | 
					 | 
				
			||||||
	cache_flush();
 | 
					 | 
				
			||||||
out_unlock:
 | 
					 | 
				
			||||||
	exp_writeunlock();
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Obtain the root fh on behalf of a client.
 | 
					 * Obtain the root fh on behalf of a client.
 | 
				
			||||||
| 
						 | 
					@ -1367,7 +1047,6 @@ static void *e_start(struct seq_file *m, loff_t *pos)
 | 
				
			||||||
	unsigned hash, export;
 | 
						unsigned hash, export;
 | 
				
			||||||
	struct cache_head *ch;
 | 
						struct cache_head *ch;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	exp_readlock();
 | 
					 | 
				
			||||||
	read_lock(&svc_export_cache.hash_lock);
 | 
						read_lock(&svc_export_cache.hash_lock);
 | 
				
			||||||
	if (!n--)
 | 
						if (!n--)
 | 
				
			||||||
		return SEQ_START_TOKEN;
 | 
							return SEQ_START_TOKEN;
 | 
				
			||||||
| 
						 | 
					@ -1418,7 +1097,6 @@ static void e_stop(struct seq_file *m, void *p)
 | 
				
			||||||
	__releases(svc_export_cache.hash_lock)
 | 
						__releases(svc_export_cache.hash_lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	read_unlock(&svc_export_cache.hash_lock);
 | 
						read_unlock(&svc_export_cache.hash_lock);
 | 
				
			||||||
	exp_readunlock();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct flags {
 | 
					static struct flags {
 | 
				
			||||||
| 
						 | 
					@ -1550,97 +1228,6 @@ const struct seq_operations nfs_exports_op = {
 | 
				
			||||||
	.show	= e_show,
 | 
						.show	= e_show,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Add or modify a client.
 | 
					 | 
				
			||||||
 * Change requests may involve the list of host addresses. The list of
 | 
					 | 
				
			||||||
 * exports and possibly existing uid maps are left untouched.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
exp_addclient(struct nfsctl_client *ncp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct auth_domain	*dom;
 | 
					 | 
				
			||||||
	int			i, err;
 | 
					 | 
				
			||||||
	struct in6_addr addr6;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* First, consistency check. */
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
	if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Lock the hashtable */
 | 
					 | 
				
			||||||
	exp_writelock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dom = unix_domain_find(ncp->cl_ident);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = -ENOMEM;
 | 
					 | 
				
			||||||
	if (!dom)
 | 
					 | 
				
			||||||
		goto out_unlock;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Insert client into hashtable. */
 | 
					 | 
				
			||||||
	for (i = 0; i < ncp->cl_naddr; i++) {
 | 
					 | 
				
			||||||
		ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
 | 
					 | 
				
			||||||
		auth_unix_add_addr(&init_net, &addr6, dom);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	auth_unix_forget_old(dom);
 | 
					 | 
				
			||||||
	auth_domain_put(dom);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out_unlock:
 | 
					 | 
				
			||||||
	exp_writeunlock();
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Delete a client given an identifier.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
exp_delclient(struct nfsctl_client *ncp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int		err;
 | 
					 | 
				
			||||||
	struct auth_domain *dom;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
	if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Lock the hashtable */
 | 
					 | 
				
			||||||
	exp_writelock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dom = auth_domain_find(ncp->cl_ident);
 | 
					 | 
				
			||||||
	/* just make sure that no addresses work 
 | 
					 | 
				
			||||||
	 * and that it will expire soon 
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (dom) {
 | 
					 | 
				
			||||||
		err = auth_unix_forget_old(dom);
 | 
					 | 
				
			||||||
		auth_domain_put(dom);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exp_writeunlock();
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Verify that string is non-empty and does not exceed max length.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
exp_verify_string(char *cp, int max)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int	i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < max; i++)
 | 
					 | 
				
			||||||
		if (!cp[i])
 | 
					 | 
				
			||||||
			return i;
 | 
					 | 
				
			||||||
	cp[i] = 0;
 | 
					 | 
				
			||||||
	printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Initialize the exports module.
 | 
					 * Initialize the exports module.
 | 
				
			||||||
| 
						 | 
					@ -1667,10 +1254,8 @@ nfsd_export_init(void)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
nfsd_export_flush(void)
 | 
					nfsd_export_flush(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	exp_writelock();
 | 
					 | 
				
			||||||
	cache_purge(&svc_expkey_cache);
 | 
						cache_purge(&svc_expkey_cache);
 | 
				
			||||||
	cache_purge(&svc_export_cache);
 | 
						cache_purge(&svc_export_cache);
 | 
				
			||||||
	exp_writeunlock();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1682,12 +1267,9 @@ nfsd_export_shutdown(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dprintk("nfsd: shutting down export module.\n");
 | 
						dprintk("nfsd: shutting down export module.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exp_writelock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cache_unregister(&svc_expkey_cache);
 | 
						cache_unregister(&svc_expkey_cache);
 | 
				
			||||||
	cache_unregister(&svc_export_cache);
 | 
						cache_unregister(&svc_export_cache);
 | 
				
			||||||
	svcauth_unix_purge();
 | 
						svcauth_unix_purge();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exp_writeunlock();
 | 
					 | 
				
			||||||
	dprintk("nfsd: export shutdown complete.\n");
 | 
						dprintk("nfsd: export shutdown complete.\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,10 +35,8 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 | 
				
			||||||
	memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
 | 
						memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
 | 
				
			||||||
	fh.fh_export = NULL;
 | 
						fh.fh_export = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exp_readlock();
 | 
					 | 
				
			||||||
	nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
 | 
						nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
 | 
				
			||||||
	fh_put(&fh);
 | 
						fh_put(&fh);
 | 
				
			||||||
	exp_readunlock();
 | 
					 | 
				
			||||||
 	/* We return nlm error codes as nlm doesn't know
 | 
					 	/* We return nlm error codes as nlm doesn't know
 | 
				
			||||||
	 * about nfsd, but nfsd does know about nlm..
 | 
						 * about nfsd, but nfsd does know about nlm..
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,6 +291,15 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 | 
				
			||||||
	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
 | 
						if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
 | 
				
			||||||
		return nfserr_inval;
 | 
							return nfserr_inval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * RFC5661 18.51.3
 | 
				
			||||||
 | 
						 * Before RECLAIM_COMPLETE done, server should deny new lock
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (nfsd4_has_session(cstate) &&
 | 
				
			||||||
 | 
						    !cstate->session->se_client->cl_firststate &&
 | 
				
			||||||
 | 
						    open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
 | 
				
			||||||
 | 
							return nfserr_grace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nfsd4_has_session(cstate))
 | 
						if (nfsd4_has_session(cstate))
 | 
				
			||||||
		copy_clientid(&open->op_clientid, cstate->session);
 | 
							copy_clientid(&open->op_clientid, cstate->session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -998,6 +1007,15 @@ struct nfsd4_operation {
 | 
				
			||||||
	nfsd4op_func op_func;
 | 
						nfsd4op_func op_func;
 | 
				
			||||||
	u32 op_flags;
 | 
						u32 op_flags;
 | 
				
			||||||
	char *op_name;
 | 
						char *op_name;
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * We use the DRC for compounds containing non-idempotent
 | 
				
			||||||
 | 
						 * operations, *except* those that are 4.1-specific (since
 | 
				
			||||||
 | 
						 * sessions provide their own EOS), and except for stateful
 | 
				
			||||||
 | 
						 * operations other than setclientid and setclientid_confirm
 | 
				
			||||||
 | 
						 * (since sequence numbers provide EOS for open, lock, etc in
 | 
				
			||||||
 | 
						 * the v4.0 case).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						bool op_cacheresult;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct nfsd4_operation nfsd4_ops[];
 | 
					static struct nfsd4_operation nfsd4_ops[];
 | 
				
			||||||
| 
						 | 
					@ -1042,6 +1060,11 @@ static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
 | 
				
			||||||
	return &nfsd4_ops[op->opnum];
 | 
						return &nfsd4_ops[op->opnum];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool nfsd4_cache_this_op(struct nfsd4_op *op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return OPDESC(op)->op_cacheresult;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool need_wrongsec_check(struct svc_rqst *rqstp)
 | 
					static bool need_wrongsec_check(struct svc_rqst *rqstp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
 | 
						struct nfsd4_compoundres *resp = rqstp->rq_resp;
 | 
				
			||||||
| 
						 | 
					@ -1209,7 +1232,6 @@ encode_op:
 | 
				
			||||||
	fh_put(&resp->cstate.save_fh);
 | 
						fh_put(&resp->cstate.save_fh);
 | 
				
			||||||
	BUG_ON(resp->cstate.replay_owner);
 | 
						BUG_ON(resp->cstate.replay_owner);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	nfsd4_release_compoundargs(args);
 | 
					 | 
				
			||||||
	/* Reset deferral mechanism for RPC deferrals */
 | 
						/* Reset deferral mechanism for RPC deferrals */
 | 
				
			||||||
	rqstp->rq_usedeferral = 1;
 | 
						rqstp->rq_usedeferral = 1;
 | 
				
			||||||
	dprintk("nfsv4 compound returned %d\n", ntohl(status));
 | 
						dprintk("nfsv4 compound returned %d\n", ntohl(status));
 | 
				
			||||||
| 
						 | 
					@ -1232,6 +1254,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
	[OP_CREATE] = {
 | 
						[OP_CREATE] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_create,
 | 
							.op_func = (nfsd4op_func)nfsd4_create,
 | 
				
			||||||
		.op_name = "OP_CREATE",
 | 
							.op_name = "OP_CREATE",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_DELEGRETURN] = {
 | 
						[OP_DELEGRETURN] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_delegreturn,
 | 
							.op_func = (nfsd4op_func)nfsd4_delegreturn,
 | 
				
			||||||
| 
						 | 
					@ -1249,6 +1272,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
	[OP_LINK] = {
 | 
						[OP_LINK] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_link,
 | 
							.op_func = (nfsd4op_func)nfsd4_link,
 | 
				
			||||||
		.op_name = "OP_LINK",
 | 
							.op_name = "OP_LINK",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_LOCK] = {
 | 
						[OP_LOCK] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_lock,
 | 
							.op_func = (nfsd4op_func)nfsd4_lock,
 | 
				
			||||||
| 
						 | 
					@ -1322,10 +1346,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
	[OP_REMOVE] = {
 | 
						[OP_REMOVE] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_remove,
 | 
							.op_func = (nfsd4op_func)nfsd4_remove,
 | 
				
			||||||
		.op_name = "OP_REMOVE",
 | 
							.op_name = "OP_REMOVE",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_RENAME] = {
 | 
						[OP_RENAME] = {
 | 
				
			||||||
		.op_name = "OP_RENAME",
 | 
							.op_name = "OP_RENAME",
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_rename,
 | 
							.op_func = (nfsd4op_func)nfsd4_rename,
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_RENEW] = {
 | 
						[OP_RENEW] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_renew,
 | 
							.op_func = (nfsd4op_func)nfsd4_renew,
 | 
				
			||||||
| 
						 | 
					@ -1351,16 +1377,19 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
	[OP_SETATTR] = {
 | 
						[OP_SETATTR] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_setattr,
 | 
							.op_func = (nfsd4op_func)nfsd4_setattr,
 | 
				
			||||||
		.op_name = "OP_SETATTR",
 | 
							.op_name = "OP_SETATTR",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_SETCLIENTID] = {
 | 
						[OP_SETCLIENTID] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_setclientid,
 | 
							.op_func = (nfsd4op_func)nfsd4_setclientid,
 | 
				
			||||||
		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 | 
							.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 | 
				
			||||||
		.op_name = "OP_SETCLIENTID",
 | 
							.op_name = "OP_SETCLIENTID",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_SETCLIENTID_CONFIRM] = {
 | 
						[OP_SETCLIENTID_CONFIRM] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
 | 
							.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
 | 
				
			||||||
		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 | 
							.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 | 
				
			||||||
		.op_name = "OP_SETCLIENTID_CONFIRM",
 | 
							.op_name = "OP_SETCLIENTID_CONFIRM",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_VERIFY] = {
 | 
						[OP_VERIFY] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_verify,
 | 
							.op_func = (nfsd4op_func)nfsd4_verify,
 | 
				
			||||||
| 
						 | 
					@ -1369,6 +1398,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
	[OP_WRITE] = {
 | 
						[OP_WRITE] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_write,
 | 
							.op_func = (nfsd4op_func)nfsd4_write,
 | 
				
			||||||
		.op_name = "OP_WRITE",
 | 
							.op_name = "OP_WRITE",
 | 
				
			||||||
 | 
							.op_cacheresult = true,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	[OP_RELEASE_LOCKOWNER] = {
 | 
						[OP_RELEASE_LOCKOWNER] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
 | 
							.op_func = (nfsd4op_func)nfsd4_release_lockowner,
 | 
				
			||||||
| 
						 | 
					@ -1402,6 +1432,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
 | 
							.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
 | 
				
			||||||
		.op_name = "OP_SEQUENCE",
 | 
							.op_name = "OP_SEQUENCE",
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						[OP_DESTROY_CLIENTID] = {
 | 
				
			||||||
 | 
							.op_func = NULL,
 | 
				
			||||||
 | 
							.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
 | 
				
			||||||
 | 
							.op_name = "OP_DESTROY_CLIENTID",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	[OP_RECLAIM_COMPLETE] = {
 | 
						[OP_RECLAIM_COMPLETE] = {
 | 
				
			||||||
		.op_func = (nfsd4op_func)nfsd4_reclaim_complete,
 | 
							.op_func = (nfsd4op_func)nfsd4_reclaim_complete,
 | 
				
			||||||
		.op_flags = ALLOWED_WITHOUT_FH,
 | 
							.op_flags = ALLOWED_WITHOUT_FH,
 | 
				
			||||||
| 
						 | 
					@ -1412,6 +1447,16 @@ static struct nfsd4_operation nfsd4_ops[] = {
 | 
				
			||||||
		.op_flags = OP_HANDLES_WRONGSEC,
 | 
							.op_flags = OP_HANDLES_WRONGSEC,
 | 
				
			||||||
		.op_name = "OP_SECINFO_NO_NAME",
 | 
							.op_name = "OP_SECINFO_NO_NAME",
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						[OP_TEST_STATEID] = {
 | 
				
			||||||
 | 
							.op_func = (nfsd4op_func)nfsd4_test_stateid,
 | 
				
			||||||
 | 
							.op_flags = ALLOWED_WITHOUT_FH,
 | 
				
			||||||
 | 
							.op_name = "OP_TEST_STATEID",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[OP_FREE_STATEID] = {
 | 
				
			||||||
 | 
							.op_func = (nfsd4op_func)nfsd4_free_stateid,
 | 
				
			||||||
 | 
							.op_flags = ALLOWED_WITHOUT_FH,
 | 
				
			||||||
 | 
							.op_name = "OP_FREE_STATEID",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *nfsd4_op_name(unsigned opnum)
 | 
					static const char *nfsd4_op_name(unsigned opnum)
 | 
				
			||||||
| 
						 | 
					@ -1424,16 +1469,6 @@ static const char *nfsd4_op_name(unsigned opnum)
 | 
				
			||||||
#define nfsd4_voidres			nfsd4_voidargs
 | 
					#define nfsd4_voidres			nfsd4_voidargs
 | 
				
			||||||
struct nfsd4_voidargs { int dummy; };
 | 
					struct nfsd4_voidargs { int dummy; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * TODO: At the present time, the NFSv4 server does not do XID caching
 | 
					 | 
				
			||||||
 * of requests.  Implementing XID caching would not be a serious problem,
 | 
					 | 
				
			||||||
 * although it would require a mild change in interfaces since one
 | 
					 | 
				
			||||||
 * doesn't know whether an NFSv4 request is idempotent until after the
 | 
					 | 
				
			||||||
 * XDR decode.  However, XID caching totally confuses pynfs (Peter
 | 
					 | 
				
			||||||
 * Astrand's regression testsuite for NFSv4 servers), which reuses
 | 
					 | 
				
			||||||
 * XID's liberally, so I've left it unimplemented until pynfs generates
 | 
					 | 
				
			||||||
 * better XID's.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct svc_procedure		nfsd_procedures4[2] = {
 | 
					static struct svc_procedure		nfsd_procedures4[2] = {
 | 
				
			||||||
	[NFSPROC4_NULL] = {
 | 
						[NFSPROC4_NULL] = {
 | 
				
			||||||
		.pc_func = (svc_procfunc) nfsd4_proc_null,
 | 
							.pc_func = (svc_procfunc) nfsd4_proc_null,
 | 
				
			||||||
| 
						 | 
					@ -1449,6 +1484,7 @@ static struct svc_procedure		nfsd_procedures4[2] = {
 | 
				
			||||||
		.pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
 | 
							.pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
 | 
				
			||||||
		.pc_argsize = sizeof(struct nfsd4_compoundargs),
 | 
							.pc_argsize = sizeof(struct nfsd4_compoundargs),
 | 
				
			||||||
		.pc_ressize = sizeof(struct nfsd4_compoundres),
 | 
							.pc_ressize = sizeof(struct nfsd4_compoundres),
 | 
				
			||||||
 | 
							.pc_release = nfsd4_release_compoundargs,
 | 
				
			||||||
		.pc_cachetype = RC_NOCACHE,
 | 
							.pc_cachetype = RC_NOCACHE,
 | 
				
			||||||
		.pc_xdrressize = NFSD_BUFSIZE/4,
 | 
							.pc_xdrressize = NFSD_BUFSIZE/4,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@
 | 
				
			||||||
#include <linux/slab.h>
 | 
					#include <linux/slab.h>
 | 
				
			||||||
#include <linux/namei.h>
 | 
					#include <linux/namei.h>
 | 
				
			||||||
#include <linux/swap.h>
 | 
					#include <linux/swap.h>
 | 
				
			||||||
 | 
					#include <linux/pagemap.h>
 | 
				
			||||||
#include <linux/sunrpc/svcauth_gss.h>
 | 
					#include <linux/sunrpc/svcauth_gss.h>
 | 
				
			||||||
#include <linux/sunrpc/clnt.h>
 | 
					#include <linux/sunrpc/clnt.h>
 | 
				
			||||||
#include "xdr4.h"
 | 
					#include "xdr4.h"
 | 
				
			||||||
| 
						 | 
					@ -60,9 +61,12 @@ static u64 current_sessionid = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* forward declarations */
 | 
					/* forward declarations */
 | 
				
			||||||
static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
 | 
					static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
 | 
				
			||||||
 | 
					static struct nfs4_stateid * search_for_stateid(stateid_t *stid);
 | 
				
			||||||
 | 
					static struct nfs4_delegation * search_for_delegation(stateid_t *stid);
 | 
				
			||||||
static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
 | 
					static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
 | 
				
			||||||
static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
 | 
					static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
 | 
				
			||||||
static void nfs4_set_recdir(char *recdir);
 | 
					static void nfs4_set_recdir(char *recdir);
 | 
				
			||||||
 | 
					static int check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Locking: */
 | 
					/* Locking: */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -381,14 +385,6 @@ static int nfs4_access_to_omode(u32 access)
 | 
				
			||||||
	BUG();
 | 
						BUG();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned int access;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	set_access(&access, stp->st_access_bmap);
 | 
					 | 
				
			||||||
	return nfs4_access_to_omode(access);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void unhash_generic_stateid(struct nfs4_stateid *stp)
 | 
					static void unhash_generic_stateid(struct nfs4_stateid *stp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	list_del(&stp->st_hash);
 | 
						list_del(&stp->st_hash);
 | 
				
			||||||
| 
						 | 
					@ -398,11 +394,14 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void free_generic_stateid(struct nfs4_stateid *stp)
 | 
					static void free_generic_stateid(struct nfs4_stateid *stp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int oflag;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (stp->st_access_bmap) {
 | 
						if (stp->st_access_bmap) {
 | 
				
			||||||
		oflag = nfs4_access_bmap_to_omode(stp);
 | 
							for (i = 1; i < 4; i++) {
 | 
				
			||||||
		nfs4_file_put_access(stp->st_file, oflag);
 | 
								if (test_bit(i, &stp->st_access_bmap))
 | 
				
			||||||
 | 
									nfs4_file_put_access(stp->st_file,
 | 
				
			||||||
 | 
											nfs4_access_to_omode(i));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	put_nfs4_file(stp->st_file);
 | 
						put_nfs4_file(stp->st_file);
 | 
				
			||||||
	kmem_cache_free(stateid_slab, stp);
 | 
						kmem_cache_free(stateid_slab, stp);
 | 
				
			||||||
| 
						 | 
					@ -1507,6 +1506,29 @@ nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
 | 
				
			||||||
	return slot->sl_status;
 | 
						return slot->sl_status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NFSD_MIN_REQ_HDR_SEQ_SZ	((\
 | 
				
			||||||
 | 
								2 * 2 + /* credential,verifier: AUTH_NULL, length 0 */ \
 | 
				
			||||||
 | 
								1 +	/* MIN tag is length with zero, only length */ \
 | 
				
			||||||
 | 
								3 +	/* version, opcount, opcode */ \
 | 
				
			||||||
 | 
								XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
 | 
				
			||||||
 | 
									/* seqid, slotID, slotID, cache */ \
 | 
				
			||||||
 | 
								4 ) * sizeof(__be32))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NFSD_MIN_RESP_HDR_SEQ_SZ ((\
 | 
				
			||||||
 | 
								2 +	/* verifier: AUTH_NULL, length 0 */\
 | 
				
			||||||
 | 
								1 +	/* status */ \
 | 
				
			||||||
 | 
								1 +	/* MIN tag is length with zero, only length */ \
 | 
				
			||||||
 | 
								3 +	/* opcount, opcode, opstatus*/ \
 | 
				
			||||||
 | 
								XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
 | 
				
			||||||
 | 
									/* seqid, slotID, slotID, slotID, status */ \
 | 
				
			||||||
 | 
								5 ) * sizeof(__be32))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs fchannel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return fchannel.maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ
 | 
				
			||||||
 | 
							|| fchannel.maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__be32
 | 
					__be32
 | 
				
			||||||
nfsd4_create_session(struct svc_rqst *rqstp,
 | 
					nfsd4_create_session(struct svc_rqst *rqstp,
 | 
				
			||||||
		     struct nfsd4_compound_state *cstate,
 | 
							     struct nfsd4_compound_state *cstate,
 | 
				
			||||||
| 
						 | 
					@ -1575,6 +1597,10 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 | 
				
			||||||
	cr_ses->flags &= ~SESSION4_PERSIST;
 | 
						cr_ses->flags &= ~SESSION4_PERSIST;
 | 
				
			||||||
	cr_ses->flags &= ~SESSION4_RDMA;
 | 
						cr_ses->flags &= ~SESSION4_RDMA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = nfserr_toosmall;
 | 
				
			||||||
 | 
						if (check_forechannel_attrs(cr_ses->fore_channel))
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = nfserr_jukebox;
 | 
						status = nfserr_jukebox;
 | 
				
			||||||
	new = alloc_init_session(rqstp, conf, cr_ses);
 | 
						new = alloc_init_session(rqstp, conf, cr_ses);
 | 
				
			||||||
	if (!new)
 | 
						if (!new)
 | 
				
			||||||
| 
						 | 
					@ -1736,6 +1762,14 @@ static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_sess
 | 
				
			||||||
	return args->opcnt > session->se_fchannel.maxops;
 | 
						return args->opcnt > session->se_fchannel.maxops;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool nfsd4_request_too_big(struct svc_rqst *rqstp,
 | 
				
			||||||
 | 
									  struct nfsd4_session *session)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct xdr_buf *xb = &rqstp->rq_arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return xb->len > session->se_fchannel.maxreq_sz;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__be32
 | 
					__be32
 | 
				
			||||||
nfsd4_sequence(struct svc_rqst *rqstp,
 | 
					nfsd4_sequence(struct svc_rqst *rqstp,
 | 
				
			||||||
	       struct nfsd4_compound_state *cstate,
 | 
						       struct nfsd4_compound_state *cstate,
 | 
				
			||||||
| 
						 | 
					@ -1768,6 +1802,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 | 
				
			||||||
	if (nfsd4_session_too_many_ops(rqstp, session))
 | 
						if (nfsd4_session_too_many_ops(rqstp, session))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = nfserr_req_too_big;
 | 
				
			||||||
 | 
						if (nfsd4_request_too_big(rqstp, session))
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = nfserr_badslot;
 | 
						status = nfserr_badslot;
 | 
				
			||||||
	if (seq->slotid >= session->se_fchannel.maxreqs)
 | 
						if (seq->slotid >= session->se_fchannel.maxreqs)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -2337,15 +2375,6 @@ out:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void
 | 
					 | 
				
			||||||
nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (share_access & NFS4_SHARE_ACCESS_WRITE)
 | 
					 | 
				
			||||||
		nfs4_file_put_access(fp, O_WRONLY);
 | 
					 | 
				
			||||||
	if (share_access & NFS4_SHARE_ACCESS_READ)
 | 
					 | 
				
			||||||
		nfs4_file_put_access(fp, O_RDONLY);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
 | 
					static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* We're assuming the state code never drops its reference
 | 
						/* We're assuming the state code never drops its reference
 | 
				
			||||||
| 
						 | 
					@ -2396,8 +2425,8 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct lock_manager_operations nfsd_lease_mng_ops = {
 | 
					static const struct lock_manager_operations nfsd_lease_mng_ops = {
 | 
				
			||||||
	.fl_break = nfsd_break_deleg_cb,
 | 
						.lm_break = nfsd_break_deleg_cb,
 | 
				
			||||||
	.fl_change = nfsd_change_deleg_cb,
 | 
						.lm_change = nfsd_change_deleg_cb,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2556,12 +2585,18 @@ static inline int nfs4_access_to_access(u32 nfs4_access)
 | 
				
			||||||
	return flags;
 | 
						return flags;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file
 | 
					static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
 | 
				
			||||||
*fp, struct svc_fh *cur_fh, u32 nfs4_access)
 | 
							struct svc_fh *cur_fh, struct nfsd4_open *open)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	__be32 status;
 | 
						__be32 status;
 | 
				
			||||||
	int oflag = nfs4_access_to_omode(nfs4_access);
 | 
						int oflag = nfs4_access_to_omode(open->op_share_access);
 | 
				
			||||||
	int access = nfs4_access_to_access(nfs4_access);
 | 
						int access = nfs4_access_to_access(open->op_share_access);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* CLAIM_DELEGATE_CUR is used in response to a broken lease;
 | 
				
			||||||
 | 
						 * allowing it to break the lease and return EAGAIN leaves the
 | 
				
			||||||
 | 
						 * client unable to make progress in returning the delegation */
 | 
				
			||||||
 | 
						if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
 | 
				
			||||||
 | 
							access |= NFSD_MAY_NOT_BREAK_LEASE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!fp->fi_fds[oflag]) {
 | 
						if (!fp->fi_fds[oflag]) {
 | 
				
			||||||
		status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
 | 
							status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
 | 
				
			||||||
| 
						 | 
					@ -2586,7 +2621,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
 | 
				
			||||||
	if (stp == NULL)
 | 
						if (stp == NULL)
 | 
				
			||||||
		return nfserr_resource;
 | 
							return nfserr_resource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access);
 | 
						status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
 | 
				
			||||||
	if (status) {
 | 
						if (status) {
 | 
				
			||||||
		kmem_cache_free(stateid_slab, stp);
 | 
							kmem_cache_free(stateid_slab, stp);
 | 
				
			||||||
		return status;
 | 
							return status;
 | 
				
			||||||
| 
						 | 
					@ -2619,14 +2654,14 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new_access = !test_bit(op_share_access, &stp->st_access_bmap);
 | 
						new_access = !test_bit(op_share_access, &stp->st_access_bmap);
 | 
				
			||||||
	if (new_access) {
 | 
						if (new_access) {
 | 
				
			||||||
		status = nfs4_get_vfs_file(rqstp, fp, cur_fh, op_share_access);
 | 
							status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
 | 
				
			||||||
		if (status)
 | 
							if (status)
 | 
				
			||||||
			return status;
 | 
								return status;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	status = nfsd4_truncate(rqstp, cur_fh, open);
 | 
						status = nfsd4_truncate(rqstp, cur_fh, open);
 | 
				
			||||||
	if (status) {
 | 
						if (status) {
 | 
				
			||||||
		if (new_access) {
 | 
							if (new_access) {
 | 
				
			||||||
			int oflag = nfs4_access_to_omode(new_access);
 | 
								int oflag = nfs4_access_to_omode(op_share_access);
 | 
				
			||||||
			nfs4_file_put_access(fp, oflag);
 | 
								nfs4_file_put_access(fp, oflag);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return status;
 | 
							return status;
 | 
				
			||||||
| 
						 | 
					@ -3137,6 +3172,37 @@ static int is_delegation_stateid(stateid_t *stateid)
 | 
				
			||||||
	return stateid->si_fileid == 0;
 | 
						return stateid->si_fileid == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int is_open_stateid(struct nfs4_stateid *stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stateid->st_openstp == NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__be32 nfs4_validate_stateid(stateid_t *stateid, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs4_stateid *stp = NULL;
 | 
				
			||||||
 | 
						__be32 status = nfserr_stale_stateid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (STALE_STATEID(stateid))
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = nfserr_expired;
 | 
				
			||||||
 | 
						stp = search_for_stateid(stateid);
 | 
				
			||||||
 | 
						if (!stp)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						status = nfserr_bad_stateid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!stp->st_stateowner->so_confirmed)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = check_stateid_generation(stateid, &stp->st_stateid, flags);
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = nfs_ok;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
* Checks for stateid operations
 | 
					* Checks for stateid operations
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
| 
						 | 
					@ -3216,6 +3282,81 @@ out:
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __be32
 | 
				
			||||||
 | 
					nfsd4_free_delegation_stateid(stateid_t *stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs4_delegation *dp = search_for_delegation(stateid);
 | 
				
			||||||
 | 
						if (dp)
 | 
				
			||||||
 | 
							return nfserr_locks_held;
 | 
				
			||||||
 | 
						return nfserr_bad_stateid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __be32
 | 
				
			||||||
 | 
					nfsd4_free_lock_stateid(struct nfs4_stateid *stp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (check_for_locks(stp->st_file, stp->st_stateowner))
 | 
				
			||||||
 | 
							return nfserr_locks_held;
 | 
				
			||||||
 | 
						release_lock_stateid(stp);
 | 
				
			||||||
 | 
						return nfs_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test if the stateid is valid
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					__be32
 | 
				
			||||||
 | 
					nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 | 
				
			||||||
 | 
							   struct nfsd4_test_stateid *test_stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						test_stateid->ts_has_session = nfsd4_has_session(cstate);
 | 
				
			||||||
 | 
						return nfs_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Free a state id
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					__be32
 | 
				
			||||||
 | 
					nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 | 
				
			||||||
 | 
							   struct nfsd4_free_stateid *free_stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stateid_t *stateid = &free_stateid->fr_stateid;
 | 
				
			||||||
 | 
						struct nfs4_stateid *stp;
 | 
				
			||||||
 | 
						__be32 ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nfs4_lock_state();
 | 
				
			||||||
 | 
						if (is_delegation_stateid(stateid)) {
 | 
				
			||||||
 | 
							ret = nfsd4_free_delegation_stateid(stateid);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stp = search_for_stateid(stateid);
 | 
				
			||||||
 | 
						if (!stp) {
 | 
				
			||||||
 | 
							ret = nfserr_bad_stateid;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (stateid->si_generation != 0) {
 | 
				
			||||||
 | 
							if (stateid->si_generation < stp->st_stateid.si_generation) {
 | 
				
			||||||
 | 
								ret = nfserr_old_stateid;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (stateid->si_generation > stp->st_stateid.si_generation) {
 | 
				
			||||||
 | 
								ret = nfserr_bad_stateid;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (is_open_stateid(stp)) {
 | 
				
			||||||
 | 
							ret = nfserr_locks_held;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ret = nfsd4_free_lock_stateid(stp);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						nfs4_unlock_state();
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int
 | 
					static inline int
 | 
				
			||||||
setlkflg (int type)
 | 
					setlkflg (int type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -3384,18 +3525,15 @@ out:
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nfs4_file_downgrade(struct nfs4_stateid *stp, unsigned int to_access)
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * unset all bits in union bitmap (bmap) that
 | 
					 | 
				
			||||||
 * do not exist in share (from successful OPEN_DOWNGRADE)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
reset_union_bmap_access(unsigned long access, unsigned long *bmap)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 1; i < 4; i++) {
 | 
						for (i = 1; i < 4; i++) {
 | 
				
			||||||
		if ((i & access) != i)
 | 
							if (test_bit(i, &stp->st_access_bmap) && !(i & to_access)) {
 | 
				
			||||||
			__clear_bit(i, bmap);
 | 
								nfs4_file_put_access(stp->st_file, i);
 | 
				
			||||||
 | 
								__clear_bit(i, &stp->st_access_bmap);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3416,7 +3554,6 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	__be32 status;
 | 
						__be32 status;
 | 
				
			||||||
	struct nfs4_stateid *stp;
 | 
						struct nfs4_stateid *stp;
 | 
				
			||||||
	unsigned int share_access;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
 | 
						dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
 | 
				
			||||||
			(int)cstate->current_fh.fh_dentry->d_name.len,
 | 
								(int)cstate->current_fh.fh_dentry->d_name.len,
 | 
				
			||||||
| 
						 | 
					@ -3445,10 +3582,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 | 
				
			||||||
			stp->st_deny_bmap, od->od_share_deny);
 | 
								stp->st_deny_bmap, od->od_share_deny);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	set_access(&share_access, stp->st_access_bmap);
 | 
						nfs4_file_downgrade(stp, od->od_share_access);
 | 
				
			||||||
	nfs4_file_downgrade(stp->st_file, share_access & ~od->od_share_access);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
 | 
					 | 
				
			||||||
	reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
 | 
						reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	update_stateid(&stp->st_stateid);
 | 
						update_stateid(&stp->st_stateid);
 | 
				
			||||||
| 
						 | 
					@ -3594,6 +3729,14 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
 | 
				
			||||||
static struct list_head	lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
 | 
					static struct list_head	lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
 | 
				
			||||||
static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
 | 
					static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					same_stateid(stateid_t *id_one, stateid_t *id_two)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (id_one->si_stateownerid != id_two->si_stateownerid)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						return id_one->si_fileid == id_two->si_fileid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct nfs4_stateid *
 | 
					static struct nfs4_stateid *
 | 
				
			||||||
find_stateid(stateid_t *stid, int flags)
 | 
					find_stateid(stateid_t *stid, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -3623,6 +3766,44 @@ find_stateid(stateid_t *stid, int flags)
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nfs4_stateid *
 | 
				
			||||||
 | 
					search_for_stateid(stateid_t *stid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs4_stateid *local;
 | 
				
			||||||
 | 
						unsigned int hashval = stateid_hashval(stid->si_stateownerid, stid->si_fileid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
 | 
				
			||||||
 | 
							if (same_stateid(&local->st_stateid, stid))
 | 
				
			||||||
 | 
								return local;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
 | 
				
			||||||
 | 
							if (same_stateid(&local->st_stateid, stid))
 | 
				
			||||||
 | 
								return local;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nfs4_delegation *
 | 
				
			||||||
 | 
					search_for_delegation(stateid_t *stid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs4_file *fp;
 | 
				
			||||||
 | 
						struct nfs4_delegation *dp;
 | 
				
			||||||
 | 
						struct list_head *pos;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < FILE_HASH_SIZE; i++) {
 | 
				
			||||||
 | 
							list_for_each_entry(fp, &file_hashtbl[i], fi_hash) {
 | 
				
			||||||
 | 
								list_for_each(pos, &fp->fi_delegations) {
 | 
				
			||||||
 | 
									dp = list_entry(pos, struct nfs4_delegation, dl_perfile);
 | 
				
			||||||
 | 
									if (same_stateid(&dp->dl_stateid, stid))
 | 
				
			||||||
 | 
										return dp;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct nfs4_delegation *
 | 
					static struct nfs4_delegation *
 | 
				
			||||||
find_delegation_stateid(struct inode *ino, stateid_t *stid)
 | 
					find_delegation_stateid(struct inode *ino, stateid_t *stid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,13 +44,15 @@
 | 
				
			||||||
#include <linux/namei.h>
 | 
					#include <linux/namei.h>
 | 
				
			||||||
#include <linux/statfs.h>
 | 
					#include <linux/statfs.h>
 | 
				
			||||||
#include <linux/utsname.h>
 | 
					#include <linux/utsname.h>
 | 
				
			||||||
 | 
					#include <linux/pagemap.h>
 | 
				
			||||||
#include <linux/sunrpc/svcauth_gss.h>
 | 
					#include <linux/sunrpc/svcauth_gss.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "idmap.h"
 | 
					#include "idmap.h"
 | 
				
			||||||
#include "acl.h"
 | 
					#include "acl.h"
 | 
				
			||||||
#include "xdr4.h"
 | 
					#include "xdr4.h"
 | 
				
			||||||
#include "vfs.h"
 | 
					#include "vfs.h"
 | 
				
			||||||
 | 
					#include "state.h"
 | 
				
			||||||
 | 
					#include "cache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NFSDDBG_FACILITY		NFSDDBG_XDR
 | 
					#define NFSDDBG_FACILITY		NFSDDBG_XDR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,6 +133,22 @@ xdr_error:					\
 | 
				
			||||||
	}					\
 | 
						}					\
 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						savep->p        = argp->p;
 | 
				
			||||||
 | 
						savep->end      = argp->end;
 | 
				
			||||||
 | 
						savep->pagelen  = argp->pagelen;
 | 
				
			||||||
 | 
						savep->pagelist = argp->pagelist;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						argp->p        = savep->p;
 | 
				
			||||||
 | 
						argp->end      = savep->end;
 | 
				
			||||||
 | 
						argp->pagelen  = savep->pagelen;
 | 
				
			||||||
 | 
						argp->pagelist = savep->pagelist;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
 | 
					static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* We want more bytes than seem to be available.
 | 
						/* We want more bytes than seem to be available.
 | 
				
			||||||
| 
						 | 
					@ -1245,6 +1263,19 @@ nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
 | 
				
			||||||
	DECODE_TAIL;
 | 
						DECODE_TAIL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __be32
 | 
				
			||||||
 | 
					nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
 | 
				
			||||||
 | 
								  struct nfsd4_free_stateid *free_stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DECODE_HEAD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						READ_BUF(sizeof(stateid_t));
 | 
				
			||||||
 | 
						READ32(free_stateid->fr_stateid.si_generation);
 | 
				
			||||||
 | 
						COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DECODE_TAIL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __be32
 | 
					static __be32
 | 
				
			||||||
nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 | 
					nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 | 
				
			||||||
		      struct nfsd4_sequence *seq)
 | 
							      struct nfsd4_sequence *seq)
 | 
				
			||||||
| 
						 | 
					@ -1261,6 +1292,40 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 | 
				
			||||||
	DECODE_TAIL;
 | 
						DECODE_TAIL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __be32
 | 
				
			||||||
 | 
					nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int nbytes;
 | 
				
			||||||
 | 
						stateid_t si;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						__be32 *p;
 | 
				
			||||||
 | 
						__be32 status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						READ_BUF(4);
 | 
				
			||||||
 | 
						test_stateid->ts_num_ids = ntohl(*p++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nbytes = test_stateid->ts_num_ids * sizeof(stateid_t);
 | 
				
			||||||
 | 
						if (nbytes > (u32)((char *)argp->end - (char *)argp->p))
 | 
				
			||||||
 | 
							goto xdr_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						test_stateid->ts_saved_args = argp;
 | 
				
			||||||
 | 
						save_buf(argp, &test_stateid->ts_savedp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < test_stateid->ts_num_ids; i++) {
 | 
				
			||||||
 | 
							status = nfsd4_decode_stateid(argp, &si);
 | 
				
			||||||
 | 
							if (status)
 | 
				
			||||||
 | 
								return status;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status = 0;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					xdr_error:
 | 
				
			||||||
 | 
						dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
 | 
				
			||||||
 | 
						status = nfserr_bad_xdr;
 | 
				
			||||||
 | 
						goto out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
 | 
					static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	DECODE_HEAD;
 | 
						DECODE_HEAD;
 | 
				
			||||||
| 
						 | 
					@ -1370,7 +1435,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
 | 
				
			||||||
	[OP_EXCHANGE_ID]	= (nfsd4_dec)nfsd4_decode_exchange_id,
 | 
						[OP_EXCHANGE_ID]	= (nfsd4_dec)nfsd4_decode_exchange_id,
 | 
				
			||||||
	[OP_CREATE_SESSION]	= (nfsd4_dec)nfsd4_decode_create_session,
 | 
						[OP_CREATE_SESSION]	= (nfsd4_dec)nfsd4_decode_create_session,
 | 
				
			||||||
	[OP_DESTROY_SESSION]	= (nfsd4_dec)nfsd4_decode_destroy_session,
 | 
						[OP_DESTROY_SESSION]	= (nfsd4_dec)nfsd4_decode_destroy_session,
 | 
				
			||||||
	[OP_FREE_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_FREE_STATEID]	= (nfsd4_dec)nfsd4_decode_free_stateid,
 | 
				
			||||||
	[OP_GET_DIR_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_GET_DIR_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
				
			||||||
	[OP_GETDEVICEINFO]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_GETDEVICEINFO]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
				
			||||||
	[OP_GETDEVICELIST]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_GETDEVICELIST]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
				
			||||||
| 
						 | 
					@ -1380,7 +1445,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
 | 
				
			||||||
	[OP_SECINFO_NO_NAME]	= (nfsd4_dec)nfsd4_decode_secinfo_no_name,
 | 
						[OP_SECINFO_NO_NAME]	= (nfsd4_dec)nfsd4_decode_secinfo_no_name,
 | 
				
			||||||
	[OP_SEQUENCE]		= (nfsd4_dec)nfsd4_decode_sequence,
 | 
						[OP_SEQUENCE]		= (nfsd4_dec)nfsd4_decode_sequence,
 | 
				
			||||||
	[OP_SET_SSV]		= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_SET_SSV]		= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
				
			||||||
	[OP_TEST_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_TEST_STATEID]	= (nfsd4_dec)nfsd4_decode_test_stateid,
 | 
				
			||||||
	[OP_WANT_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_WANT_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
				
			||||||
	[OP_DESTROY_CLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
						[OP_DESTROY_CLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
 | 
				
			||||||
	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
 | 
						[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
 | 
				
			||||||
| 
						 | 
					@ -1402,6 +1467,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 | 
				
			||||||
	DECODE_HEAD;
 | 
						DECODE_HEAD;
 | 
				
			||||||
	struct nfsd4_op *op;
 | 
						struct nfsd4_op *op;
 | 
				
			||||||
	struct nfsd4_minorversion_ops *ops;
 | 
						struct nfsd4_minorversion_ops *ops;
 | 
				
			||||||
 | 
						bool cachethis = false;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -1483,7 +1549,16 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 | 
				
			||||||
			argp->opcnt = i+1;
 | 
								argp->opcnt = i+1;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * We'll try to cache the result in the DRC if any one
 | 
				
			||||||
 | 
							 * op in the compound wants to be cached:
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							cachethis |= nfsd4_cache_this_op(op);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						/* Sessions make the DRC unnecessary: */
 | 
				
			||||||
 | 
						if (argp->minorversion)
 | 
				
			||||||
 | 
							cachethis = false;
 | 
				
			||||||
 | 
						argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DECODE_TAIL;
 | 
						DECODE_TAIL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3115,6 +3190,21 @@ nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr,
 | 
				
			||||||
	return nfserr;
 | 
						return nfserr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __be32
 | 
				
			||||||
 | 
					nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, int nfserr,
 | 
				
			||||||
 | 
								  struct nfsd4_free_stateid *free_stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__be32 *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nfserr)
 | 
				
			||||||
 | 
							return nfserr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RESERVE_SPACE(4);
 | 
				
			||||||
 | 
						WRITE32(nfserr);
 | 
				
			||||||
 | 
						ADJUST_ARGS();
 | 
				
			||||||
 | 
						return nfserr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __be32
 | 
					static __be32
 | 
				
			||||||
nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
 | 
					nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
 | 
				
			||||||
		      struct nfsd4_sequence *seq)
 | 
							      struct nfsd4_sequence *seq)
 | 
				
			||||||
| 
						 | 
					@ -3138,6 +3228,36 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__be32
 | 
				
			||||||
 | 
					nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
 | 
				
			||||||
 | 
								  struct nfsd4_test_stateid *test_stateid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfsd4_compoundargs *argp;
 | 
				
			||||||
 | 
						stateid_t si;
 | 
				
			||||||
 | 
						__be32 *p;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int valid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp);
 | 
				
			||||||
 | 
						argp = test_stateid->ts_saved_args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RESERVE_SPACE(4);
 | 
				
			||||||
 | 
						*p++ = htonl(test_stateid->ts_num_ids);
 | 
				
			||||||
 | 
						resp->p = p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nfs4_lock_state();
 | 
				
			||||||
 | 
						for (i = 0; i < test_stateid->ts_num_ids; i++) {
 | 
				
			||||||
 | 
							nfsd4_decode_stateid(argp, &si);
 | 
				
			||||||
 | 
							valid = nfs4_validate_stateid(&si, test_stateid->ts_has_session);
 | 
				
			||||||
 | 
							RESERVE_SPACE(4);
 | 
				
			||||||
 | 
							*p++ = htonl(valid);
 | 
				
			||||||
 | 
							resp->p = p;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						nfs4_unlock_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nfserr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __be32
 | 
					static __be32
 | 
				
			||||||
nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
 | 
					nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -3196,7 +3316,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
 | 
				
			||||||
	[OP_EXCHANGE_ID]	= (nfsd4_enc)nfsd4_encode_exchange_id,
 | 
						[OP_EXCHANGE_ID]	= (nfsd4_enc)nfsd4_encode_exchange_id,
 | 
				
			||||||
	[OP_CREATE_SESSION]	= (nfsd4_enc)nfsd4_encode_create_session,
 | 
						[OP_CREATE_SESSION]	= (nfsd4_enc)nfsd4_encode_create_session,
 | 
				
			||||||
	[OP_DESTROY_SESSION]	= (nfsd4_enc)nfsd4_encode_destroy_session,
 | 
						[OP_DESTROY_SESSION]	= (nfsd4_enc)nfsd4_encode_destroy_session,
 | 
				
			||||||
	[OP_FREE_STATEID]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_FREE_STATEID]	= (nfsd4_enc)nfsd4_encode_free_stateid,
 | 
				
			||||||
	[OP_GET_DIR_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_GET_DIR_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
	[OP_GETDEVICEINFO]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_GETDEVICEINFO]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
	[OP_GETDEVICELIST]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_GETDEVICELIST]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
| 
						 | 
					@ -3206,7 +3326,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
 | 
				
			||||||
	[OP_SECINFO_NO_NAME]	= (nfsd4_enc)nfsd4_encode_secinfo_no_name,
 | 
						[OP_SECINFO_NO_NAME]	= (nfsd4_enc)nfsd4_encode_secinfo_no_name,
 | 
				
			||||||
	[OP_SEQUENCE]		= (nfsd4_enc)nfsd4_encode_sequence,
 | 
						[OP_SEQUENCE]		= (nfsd4_enc)nfsd4_encode_sequence,
 | 
				
			||||||
	[OP_SET_SSV]		= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_SET_SSV]		= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
	[OP_TEST_STATEID]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_TEST_STATEID]	= (nfsd4_enc)nfsd4_encode_test_stateid,
 | 
				
			||||||
	[OP_WANT_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_WANT_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
	[OP_DESTROY_CLIENTID]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_DESTROY_CLIENTID]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
	[OP_RECLAIM_COMPLETE]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
						[OP_RECLAIM_COMPLETE]	= (nfsd4_enc)nfsd4_encode_noop,
 | 
				
			||||||
| 
						 | 
					@ -3319,8 +3439,11 @@ nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 | 
				
			||||||
        return xdr_ressize_check(rqstp, p);
 | 
					        return xdr_ressize_check(rqstp, p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
 | 
					int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct svc_rqst *rqstp = rq;
 | 
				
			||||||
 | 
						struct nfsd4_compoundargs *args = rqstp->rq_argp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args->ops != args->iops) {
 | 
						if (args->ops != args->iops) {
 | 
				
			||||||
		kfree(args->ops);
 | 
							kfree(args->ops);
 | 
				
			||||||
		args->ops = args->iops;
 | 
							args->ops = args->iops;
 | 
				
			||||||
| 
						 | 
					@ -3333,13 +3456,12 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
 | 
				
			||||||
		tb->release(tb->buf);
 | 
							tb->release(tb->buf);
 | 
				
			||||||
		kfree(tb);
 | 
							kfree(tb);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
 | 
					nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	__be32 status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	args->p = p;
 | 
						args->p = p;
 | 
				
			||||||
	args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
 | 
						args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
 | 
				
			||||||
	args->pagelist = rqstp->rq_arg.pages;
 | 
						args->pagelist = rqstp->rq_arg.pages;
 | 
				
			||||||
| 
						 | 
					@ -3349,11 +3471,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_comp
 | 
				
			||||||
	args->ops = args->iops;
 | 
						args->ops = args->iops;
 | 
				
			||||||
	args->rqstp = rqstp;
 | 
						args->rqstp = rqstp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = nfsd4_decode_compound(args);
 | 
						return !nfsd4_decode_compound(args);
 | 
				
			||||||
	if (status) {
 | 
					 | 
				
			||||||
		nfsd4_release_compoundargs(args);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return !status;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ hash_refile(struct svc_cacherep *rp)
 | 
				
			||||||
 * Note that no operation within the loop may sleep.
 | 
					 * Note that no operation within the loop may sleep.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
 | 
					nfsd_cache_lookup(struct svc_rqst *rqstp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hlist_node	*hn;
 | 
						struct hlist_node	*hn;
 | 
				
			||||||
	struct hlist_head 	*rh;
 | 
						struct hlist_head 	*rh;
 | 
				
			||||||
| 
						 | 
					@ -128,6 +128,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
 | 
				
			||||||
				vers = rqstp->rq_vers,
 | 
									vers = rqstp->rq_vers,
 | 
				
			||||||
				proc = rqstp->rq_proc;
 | 
									proc = rqstp->rq_proc;
 | 
				
			||||||
	unsigned long		age;
 | 
						unsigned long		age;
 | 
				
			||||||
 | 
						int type = rqstp->rq_cachetype;
 | 
				
			||||||
	int rtn;
 | 
						int rtn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rqstp->rq_cacherep = NULL;
 | 
						rqstp->rq_cacherep = NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										343
									
								
								fs/nfsd/nfsctl.c
									
										
									
									
									
								
							
							
						
						
									
										343
									
								
								fs/nfsd/nfsctl.c
									
										
									
									
									
								
							| 
						 | 
					@ -24,15 +24,6 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	NFSD_Root = 1,
 | 
						NFSD_Root = 1,
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	NFSD_Svc,
 | 
					 | 
				
			||||||
	NFSD_Add,
 | 
					 | 
				
			||||||
	NFSD_Del,
 | 
					 | 
				
			||||||
	NFSD_Export,
 | 
					 | 
				
			||||||
	NFSD_Unexport,
 | 
					 | 
				
			||||||
	NFSD_Getfd,
 | 
					 | 
				
			||||||
	NFSD_Getfs,
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	NFSD_List,
 | 
						NFSD_List,
 | 
				
			||||||
	NFSD_Export_features,
 | 
						NFSD_Export_features,
 | 
				
			||||||
	NFSD_Fh,
 | 
						NFSD_Fh,
 | 
				
			||||||
| 
						 | 
					@ -59,15 +50,6 @@ enum {
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * write() for these nodes.
 | 
					 * write() for these nodes.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
static ssize_t write_svc(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
static ssize_t write_add(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
static ssize_t write_del(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
static ssize_t write_export(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
static ssize_t write_unexport(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
static ssize_t write_getfd(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
static ssize_t write_getfs(struct file *file, char *buf, size_t size);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 | 
					static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 | 
				
			||||||
static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
 | 
					static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
 | 
				
			||||||
static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
 | 
					static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
 | 
				
			||||||
| 
						 | 
					@ -83,15 +65,6 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 | 
					static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	[NFSD_Svc] = write_svc,
 | 
					 | 
				
			||||||
	[NFSD_Add] = write_add,
 | 
					 | 
				
			||||||
	[NFSD_Del] = write_del,
 | 
					 | 
				
			||||||
	[NFSD_Export] = write_export,
 | 
					 | 
				
			||||||
	[NFSD_Unexport] = write_unexport,
 | 
					 | 
				
			||||||
	[NFSD_Getfd] = write_getfd,
 | 
					 | 
				
			||||||
	[NFSD_Getfs] = write_getfs,
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	[NFSD_Fh] = write_filehandle,
 | 
						[NFSD_Fh] = write_filehandle,
 | 
				
			||||||
	[NFSD_FO_UnlockIP] = write_unlock_ip,
 | 
						[NFSD_FO_UnlockIP] = write_unlock_ip,
 | 
				
			||||||
	[NFSD_FO_UnlockFS] = write_unlock_fs,
 | 
						[NFSD_FO_UnlockFS] = write_unlock_fs,
 | 
				
			||||||
| 
						 | 
					@ -130,16 +103,6 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
 | 
					static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	static int warned;
 | 
					 | 
				
			||||||
	if (file->f_dentry->d_name.name[0] == '.' && !warned) {
 | 
					 | 
				
			||||||
		printk(KERN_INFO
 | 
					 | 
				
			||||||
		       "Warning: \"%s\" uses deprecated NFSD interface: %s."
 | 
					 | 
				
			||||||
		       "  This will be removed in 2.6.40\n",
 | 
					 | 
				
			||||||
		       current->comm, file->f_dentry->d_name.name);
 | 
					 | 
				
			||||||
		warned = 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	if (! file->private_data) {
 | 
						if (! file->private_data) {
 | 
				
			||||||
		/* An attempt to read a transaction file without writing
 | 
							/* An attempt to read a transaction file without writing
 | 
				
			||||||
		 * causes a 0-byte write so that the file can return
 | 
							 * causes a 0-byte write so that the file can return
 | 
				
			||||||
| 
						 | 
					@ -226,303 +189,6 @@ static const struct file_operations pool_stats_operations = {
 | 
				
			||||||
 * payload - write methods
 | 
					 * payload - write methods
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_svc - Start kernel's NFSD server
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/fs/nfsd/threads is preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_svc
 | 
					 | 
				
			||||||
 *				svc_port:	port number of this
 | 
					 | 
				
			||||||
 *						server's listener
 | 
					 | 
				
			||||||
 *				svc_nthreads:	number of threads to start
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_svc
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	returns zero
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_svc(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_svc *data;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_svc*) buf;
 | 
					 | 
				
			||||||
	err = nfsd_svc(data->svc_port, data->svc_nthreads);
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
					 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_add - Add or modify client entry in auth unix cache
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/net/rpc/auth.unix.ip is preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_client
 | 
					 | 
				
			||||||
 *				cl_ident:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing domain name
 | 
					 | 
				
			||||||
 *						of client
 | 
					 | 
				
			||||||
 *				cl_naddr:	no. of items in cl_addrlist
 | 
					 | 
				
			||||||
 *				cl_addrlist:	array of client addresses
 | 
					 | 
				
			||||||
 *				cl_fhkeytype:	ignored
 | 
					 | 
				
			||||||
 *				cl_fhkeylen:	ignored
 | 
					 | 
				
			||||||
 *				cl_fhkey:	ignored
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_client
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	returns zero
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note: Only AF_INET client addresses are passed in, since
 | 
					 | 
				
			||||||
 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_add(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_client *data;
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_client *)buf;
 | 
					 | 
				
			||||||
	return exp_addclient(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_del - Remove client from auth unix cache
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/net/rpc/auth.unix.ip is preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_client
 | 
					 | 
				
			||||||
 *				cl_ident:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing domain name
 | 
					 | 
				
			||||||
 *						of client
 | 
					 | 
				
			||||||
 *				cl_naddr:	ignored
 | 
					 | 
				
			||||||
 *				cl_addrlist:	ignored
 | 
					 | 
				
			||||||
 *				cl_fhkeytype:	ignored
 | 
					 | 
				
			||||||
 *				cl_fhkeylen:	ignored
 | 
					 | 
				
			||||||
 *				cl_fhkey:	ignored
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_client
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	returns zero
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note: Only AF_INET client addresses are passed in, since
 | 
					 | 
				
			||||||
 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_del(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_client *data;
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_client *)buf;
 | 
					 | 
				
			||||||
	return exp_delclient(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_export - Export part or all of a local file system
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_export
 | 
					 | 
				
			||||||
 *				ex_client:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing domain name
 | 
					 | 
				
			||||||
 *						of client allowed to access
 | 
					 | 
				
			||||||
 *						this export
 | 
					 | 
				
			||||||
 *				ex_path:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing pathname of
 | 
					 | 
				
			||||||
 *						directory in local file system
 | 
					 | 
				
			||||||
 *				ex_dev:		fsid to use for this export
 | 
					 | 
				
			||||||
 *				ex_ino:		ignored
 | 
					 | 
				
			||||||
 *				ex_flags:	export flags for this export
 | 
					 | 
				
			||||||
 *				ex_anon_uid:	UID to use for anonymous
 | 
					 | 
				
			||||||
 *						requests
 | 
					 | 
				
			||||||
 *				ex_anon_gid:	GID to use for anonymous
 | 
					 | 
				
			||||||
 *						requests
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_export
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	returns zero
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_export(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_export *data;
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_export*)buf;
 | 
					 | 
				
			||||||
	return exp_export(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_unexport - Unexport a previously exported file system
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_export
 | 
					 | 
				
			||||||
 *				ex_client:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing domain name
 | 
					 | 
				
			||||||
 *						of client no longer allowed
 | 
					 | 
				
			||||||
 *						to access this export
 | 
					 | 
				
			||||||
 *				ex_path:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing pathname of
 | 
					 | 
				
			||||||
 *						directory in local file system
 | 
					 | 
				
			||||||
 *				ex_dev:		ignored
 | 
					 | 
				
			||||||
 *				ex_ino:		ignored
 | 
					 | 
				
			||||||
 *				ex_flags:	ignored
 | 
					 | 
				
			||||||
 *				ex_anon_uid:	ignored
 | 
					 | 
				
			||||||
 *				ex_anon_gid:	ignored
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_export
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	returns zero
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_unexport(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_export *data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_export*)buf;
 | 
					 | 
				
			||||||
	return exp_unexport(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_getfs - Get a variable-length NFS file handle by path
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/fs/nfsd/filehandle is preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_fsparm
 | 
					 | 
				
			||||||
 *				gd_addr:	socket address of client
 | 
					 | 
				
			||||||
 *				gd_path:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing pathname of
 | 
					 | 
				
			||||||
 *						directory in local file system
 | 
					 | 
				
			||||||
 *				gd_maxlen:	maximum size of returned file
 | 
					 | 
				
			||||||
 *						handle
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_fsparm
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	passed-in buffer filled with a knfsd_fh structure
 | 
					 | 
				
			||||||
 *			(a variable-length raw NFS file handle);
 | 
					 | 
				
			||||||
 *			return code is the size in bytes of the file handle
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note: Only AF_INET client addresses are passed in, since gd_addr
 | 
					 | 
				
			||||||
 * is the same size as a struct sockaddr_in.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_getfs(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_fsparm *data;
 | 
					 | 
				
			||||||
	struct sockaddr_in *sin;
 | 
					 | 
				
			||||||
	struct auth_domain *clp;
 | 
					 | 
				
			||||||
	int err = 0;
 | 
					 | 
				
			||||||
	struct knfsd_fh *res;
 | 
					 | 
				
			||||||
	struct in6_addr in6;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_fsparm*)buf;
 | 
					 | 
				
			||||||
	err = -EPROTONOSUPPORT;
 | 
					 | 
				
			||||||
	if (data->gd_addr.sa_family != AF_INET)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	sin = (struct sockaddr_in *)&data->gd_addr;
 | 
					 | 
				
			||||||
	if (data->gd_maxlen > NFS3_FHSIZE)
 | 
					 | 
				
			||||||
		data->gd_maxlen = NFS3_FHSIZE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res = (struct knfsd_fh*)buf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exp_readlock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clp = auth_unix_lookup(&init_net, &in6);
 | 
					 | 
				
			||||||
	if (!clp)
 | 
					 | 
				
			||||||
		err = -EPERM;
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
 | 
					 | 
				
			||||||
		auth_domain_put(clp);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	exp_readunlock();
 | 
					 | 
				
			||||||
	if (err == 0)
 | 
					 | 
				
			||||||
		err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
 | 
					 | 
				
			||||||
 out:
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Deprecated.  /proc/fs/nfsd/filehandle is preferred.
 | 
					 | 
				
			||||||
 * Function remains to support old versions of nfs-utils.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *			buf:	struct nfsctl_fdparm
 | 
					 | 
				
			||||||
 *				gd_addr:	socket address of client
 | 
					 | 
				
			||||||
 *				gd_path:	'\0'-terminated C string
 | 
					 | 
				
			||||||
 *						containing pathname of
 | 
					 | 
				
			||||||
 *						directory in local file system
 | 
					 | 
				
			||||||
 *				gd_version:	fdparm structure version
 | 
					 | 
				
			||||||
 *			size:	size in bytes of passed in nfsctl_fdparm
 | 
					 | 
				
			||||||
 * Output:
 | 
					 | 
				
			||||||
 *	On success:	passed-in buffer filled with nfsctl_res
 | 
					 | 
				
			||||||
 *			(a fixed-length raw NFS file handle);
 | 
					 | 
				
			||||||
 *			return code is the size in bytes of the file handle
 | 
					 | 
				
			||||||
 *	On error:	return code is negative errno value
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note: Only AF_INET client addresses are passed in, since gd_addr
 | 
					 | 
				
			||||||
 * is the same size as a struct sockaddr_in.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static ssize_t write_getfd(struct file *file, char *buf, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct nfsctl_fdparm *data;
 | 
					 | 
				
			||||||
	struct sockaddr_in *sin;
 | 
					 | 
				
			||||||
	struct auth_domain *clp;
 | 
					 | 
				
			||||||
	int err = 0;
 | 
					 | 
				
			||||||
	struct knfsd_fh fh;
 | 
					 | 
				
			||||||
	char *res;
 | 
					 | 
				
			||||||
	struct in6_addr in6;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (size < sizeof(*data))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	data = (struct nfsctl_fdparm*)buf;
 | 
					 | 
				
			||||||
	err = -EPROTONOSUPPORT;
 | 
					 | 
				
			||||||
	if (data->gd_addr.sa_family != AF_INET)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	err = -EINVAL;
 | 
					 | 
				
			||||||
	if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res = buf;
 | 
					 | 
				
			||||||
	sin = (struct sockaddr_in *)&data->gd_addr;
 | 
					 | 
				
			||||||
	exp_readlock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clp = auth_unix_lookup(&init_net, &in6);
 | 
					 | 
				
			||||||
	if (!clp)
 | 
					 | 
				
			||||||
		err = -EPERM;
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
 | 
					 | 
				
			||||||
		auth_domain_put(clp);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	exp_readunlock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (err == 0) {
 | 
					 | 
				
			||||||
		memset(res,0, NFS_FHSIZE);
 | 
					 | 
				
			||||||
		memcpy(res, &fh.fh_base, fh.fh_size);
 | 
					 | 
				
			||||||
		err = NFS_FHSIZE;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 out:
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * write_unlock_ip - Release all locks used by a client
 | 
					 * write_unlock_ip - Release all locks used by a client
 | 
				
			||||||
| 
						 | 
					@ -1397,15 +1063,6 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
 | 
				
			||||||
static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 | 
					static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static struct tree_descr nfsd_files[] = {
 | 
						static struct tree_descr nfsd_files[] = {
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
		[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
 | 
					 | 
				
			||||||
		[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
 | 
					 | 
				
			||||||
		[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
 | 
					 | 
				
			||||||
		[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
 | 
					 | 
				
			||||||
		[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
 | 
					 | 
				
			||||||
		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
 | 
					 | 
				
			||||||
		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
 | 
							[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
 | 
				
			||||||
		[NFSD_Export_features] = {"export_features",
 | 
							[NFSD_Export_features] = {"export_features",
 | 
				
			||||||
					&export_features_operations, S_IRUGO},
 | 
										&export_features_operations, S_IRUGO},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -528,16 +528,9 @@ nfsd(void *vrqstp)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Lock the export hash tables for reading. */
 | 
					 | 
				
			||||||
		exp_readlock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		validate_process_creds();
 | 
							validate_process_creds();
 | 
				
			||||||
		svc_process(rqstp);
 | 
							svc_process(rqstp);
 | 
				
			||||||
		validate_process_creds();
 | 
							validate_process_creds();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Unlock export hash tables */
 | 
					 | 
				
			||||||
		exp_readunlock();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clear signals before calling svc_exit_thread() */
 | 
						/* Clear signals before calling svc_exit_thread() */
 | 
				
			||||||
| 
						 | 
					@ -577,8 +570,22 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 | 
				
			||||||
				rqstp->rq_vers, rqstp->rq_proc);
 | 
									rqstp->rq_vers, rqstp->rq_proc);
 | 
				
			||||||
	proc = rqstp->rq_procinfo;
 | 
						proc = rqstp->rq_procinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Give the xdr decoder a chance to change this if it wants
 | 
				
			||||||
 | 
						 * (necessary in the NFSv4.0 compound case)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						rqstp->rq_cachetype = proc->pc_cachetype;
 | 
				
			||||||
 | 
						/* Decode arguments */
 | 
				
			||||||
 | 
						xdr = proc->pc_decode;
 | 
				
			||||||
 | 
						if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
 | 
				
			||||||
 | 
								rqstp->rq_argp)) {
 | 
				
			||||||
 | 
							dprintk("nfsd: failed to decode arguments!\n");
 | 
				
			||||||
 | 
							*statp = rpc_garbage_args;
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check whether we have this call in the cache. */
 | 
						/* Check whether we have this call in the cache. */
 | 
				
			||||||
	switch (nfsd_cache_lookup(rqstp, proc->pc_cachetype)) {
 | 
						switch (nfsd_cache_lookup(rqstp)) {
 | 
				
			||||||
	case RC_INTR:
 | 
						case RC_INTR:
 | 
				
			||||||
	case RC_DROPIT:
 | 
						case RC_DROPIT:
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -588,16 +595,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 | 
				
			||||||
		/* do it */
 | 
							/* do it */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Decode arguments */
 | 
					 | 
				
			||||||
	xdr = proc->pc_decode;
 | 
					 | 
				
			||||||
	if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
 | 
					 | 
				
			||||||
			rqstp->rq_argp)) {
 | 
					 | 
				
			||||||
		dprintk("nfsd: failed to decode arguments!\n");
 | 
					 | 
				
			||||||
		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
 | 
					 | 
				
			||||||
		*statp = rpc_garbage_args;
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* need to grab the location to store the status, as
 | 
						/* need to grab the location to store the status, as
 | 
				
			||||||
	 * nfsv4 does some encoding while processing 
 | 
						 * nfsv4 does some encoding while processing 
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -482,6 +482,7 @@ extern void nfsd4_recdir_purge_old(void);
 | 
				
			||||||
extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
 | 
					extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
 | 
				
			||||||
extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
 | 
					extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
 | 
				
			||||||
extern void release_session_client(struct nfsd4_session *);
 | 
					extern void release_session_client(struct nfsd4_session *);
 | 
				
			||||||
 | 
					extern __be32 nfs4_validate_stateid(stateid_t *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void
 | 
					static inline void
 | 
				
			||||||
nfs4_put_stateowner(struct nfs4_stateowner *so)
 | 
					nfs4_put_stateowner(struct nfs4_stateowner *so)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,6 +342,25 @@ struct nfsd4_setclientid_confirm {
 | 
				
			||||||
	nfs4_verifier	sc_confirm;
 | 
						nfs4_verifier	sc_confirm;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nfsd4_saved_compoundargs {
 | 
				
			||||||
 | 
						__be32 *p;
 | 
				
			||||||
 | 
						__be32 *end;
 | 
				
			||||||
 | 
						int pagelen;
 | 
				
			||||||
 | 
						struct page **pagelist;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nfsd4_test_stateid {
 | 
				
			||||||
 | 
						__be32		ts_num_ids;
 | 
				
			||||||
 | 
						__be32		ts_has_session;
 | 
				
			||||||
 | 
						struct nfsd4_compoundargs *ts_saved_args;
 | 
				
			||||||
 | 
						struct nfsd4_saved_compoundargs ts_savedp;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nfsd4_free_stateid {
 | 
				
			||||||
 | 
						stateid_t	fr_stateid;         /* request */
 | 
				
			||||||
 | 
						__be32		fr_status;          /* response */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* also used for NVERIFY */
 | 
					/* also used for NVERIFY */
 | 
				
			||||||
struct nfsd4_verify {
 | 
					struct nfsd4_verify {
 | 
				
			||||||
	u32		ve_bmval[3];        /* request */
 | 
						u32		ve_bmval[3];        /* request */
 | 
				
			||||||
| 
						 | 
					@ -432,10 +451,14 @@ struct nfsd4_op {
 | 
				
			||||||
		struct nfsd4_destroy_session	destroy_session;
 | 
							struct nfsd4_destroy_session	destroy_session;
 | 
				
			||||||
		struct nfsd4_sequence		sequence;
 | 
							struct nfsd4_sequence		sequence;
 | 
				
			||||||
		struct nfsd4_reclaim_complete	reclaim_complete;
 | 
							struct nfsd4_reclaim_complete	reclaim_complete;
 | 
				
			||||||
 | 
							struct nfsd4_test_stateid	test_stateid;
 | 
				
			||||||
 | 
							struct nfsd4_free_stateid	free_stateid;
 | 
				
			||||||
	} u;
 | 
						} u;
 | 
				
			||||||
	struct nfs4_replay *			replay;
 | 
						struct nfs4_replay *			replay;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool nfsd4_cache_this_op(struct nfsd4_op *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nfsd4_compoundargs {
 | 
					struct nfsd4_compoundargs {
 | 
				
			||||||
	/* scratch variables for XDR decode */
 | 
						/* scratch variables for XDR decode */
 | 
				
			||||||
	__be32 *			p;
 | 
						__be32 *			p;
 | 
				
			||||||
| 
						 | 
					@ -458,6 +481,7 @@ struct nfsd4_compoundargs {
 | 
				
			||||||
	u32				opcnt;
 | 
						u32				opcnt;
 | 
				
			||||||
	struct nfsd4_op			*ops;
 | 
						struct nfsd4_op			*ops;
 | 
				
			||||||
	struct nfsd4_op			iops[8];
 | 
						struct nfsd4_op			iops[8];
 | 
				
			||||||
 | 
						int				cachetype;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nfsd4_compoundres {
 | 
					struct nfsd4_compoundres {
 | 
				
			||||||
| 
						 | 
					@ -559,11 +583,15 @@ extern __be32
 | 
				
			||||||
nfsd4_release_lockowner(struct svc_rqst *rqstp,
 | 
					nfsd4_release_lockowner(struct svc_rqst *rqstp,
 | 
				
			||||||
		struct nfsd4_compound_state *,
 | 
							struct nfsd4_compound_state *,
 | 
				
			||||||
		struct nfsd4_release_lockowner *rlockowner);
 | 
							struct nfsd4_release_lockowner *rlockowner);
 | 
				
			||||||
extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
 | 
					extern int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp);
 | 
				
			||||||
extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
 | 
					extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
 | 
				
			||||||
		struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
 | 
							struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
 | 
				
			||||||
extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
 | 
					extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
 | 
				
			||||||
			  struct nfsd4_compound_state *, clientid_t *clid);
 | 
								  struct nfsd4_compound_state *, clientid_t *clid);
 | 
				
			||||||
 | 
					extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
 | 
				
			||||||
 | 
							struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid);
 | 
				
			||||||
 | 
					extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
 | 
				
			||||||
 | 
							struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -438,16 +438,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 | 
				
			||||||
				 struct compat_timespec __user *tsp,
 | 
									 struct compat_timespec __user *tsp,
 | 
				
			||||||
				 const compat_sigset_t __user *sigmask,
 | 
									 const compat_sigset_t __user *sigmask,
 | 
				
			||||||
				 compat_size_t sigsetsize);
 | 
									 compat_size_t sigsetsize);
 | 
				
			||||||
#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && \
 | 
					 | 
				
			||||||
	!defined(CONFIG_NFSD_DEPRECATED)
 | 
					 | 
				
			||||||
union compat_nfsctl_res;
 | 
					 | 
				
			||||||
struct compat_nfsctl_arg;
 | 
					 | 
				
			||||||
asmlinkage long compat_sys_nfsservctl(int cmd,
 | 
					 | 
				
			||||||
				      struct compat_nfsctl_arg __user *arg,
 | 
					 | 
				
			||||||
				      union compat_nfsctl_res __user *res);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2);
 | 
					asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
asmlinkage long compat_sys_signalfd4(int ufd,
 | 
					asmlinkage long compat_sys_signalfd4(int ufd,
 | 
				
			||||||
				     const compat_sigset_t __user *sigmask,
 | 
									     const compat_sigset_t __user *sigmask,
 | 
				
			||||||
				     compat_size_t sigsetsize, int flags);
 | 
									     compat_size_t sigsetsize, int flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1072,12 +1072,12 @@ struct file_lock_operations {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lock_manager_operations {
 | 
					struct lock_manager_operations {
 | 
				
			||||||
	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
 | 
						int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
 | 
				
			||||||
	void (*fl_notify)(struct file_lock *);	/* unblock callback */
 | 
						void (*lm_notify)(struct file_lock *);	/* unblock callback */
 | 
				
			||||||
	int (*fl_grant)(struct file_lock *, struct file_lock *, int);
 | 
						int (*lm_grant)(struct file_lock *, struct file_lock *, int);
 | 
				
			||||||
	void (*fl_release_private)(struct file_lock *);
 | 
						void (*lm_release_private)(struct file_lock *);
 | 
				
			||||||
	void (*fl_break)(struct file_lock *);
 | 
						void (*lm_break)(struct file_lock *);
 | 
				
			||||||
	int (*fl_change)(struct file_lock **, int);
 | 
						int (*lm_change)(struct file_lock **, int);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lock_manager {
 | 
					struct lock_manager {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,8 +133,6 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
 | 
				
			||||||
int			nfsd_export_init(void);
 | 
					int			nfsd_export_init(void);
 | 
				
			||||||
void			nfsd_export_shutdown(void);
 | 
					void			nfsd_export_shutdown(void);
 | 
				
			||||||
void			nfsd_export_flush(void);
 | 
					void			nfsd_export_flush(void);
 | 
				
			||||||
void			exp_readlock(void);
 | 
					 | 
				
			||||||
void			exp_readunlock(void);
 | 
					 | 
				
			||||||
struct svc_export *	rqst_exp_get_by_name(struct svc_rqst *,
 | 
					struct svc_export *	rqst_exp_get_by_name(struct svc_rqst *,
 | 
				
			||||||
					     struct path *);
 | 
										     struct path *);
 | 
				
			||||||
struct svc_export *	rqst_exp_parent(struct svc_rqst *,
 | 
					struct svc_export *	rqst_exp_parent(struct svc_rqst *,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,13 +256,4 @@ static inline time_t get_expiry(char **bpp)
 | 
				
			||||||
	return rv - boot.tv_sec;
 | 
						return rv - boot.tv_sec;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
static inline void sunrpc_invalidate(struct cache_head *h,
 | 
					 | 
				
			||||||
				     struct cache_detail *detail)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	h->expiry_time = seconds_since_boot() - 1;
 | 
					 | 
				
			||||||
	detail->nextcheck = seconds_since_boot();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /*  _LINUX_SUNRPC_CACHE_H_ */
 | 
					#endif /*  _LINUX_SUNRPC_CACHE_H_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -273,6 +273,7 @@ struct svc_rqst {
 | 
				
			||||||
	/* Catering to nfsd */
 | 
						/* Catering to nfsd */
 | 
				
			||||||
	struct auth_domain *	rq_client;	/* RPC peer info */
 | 
						struct auth_domain *	rq_client;	/* RPC peer info */
 | 
				
			||||||
	struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
 | 
						struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
 | 
				
			||||||
 | 
						int			rq_cachetype;
 | 
				
			||||||
	struct svc_cacherep *	rq_cacherep;	/* cache info */
 | 
						struct svc_cacherep *	rq_cacherep;	/* cache info */
 | 
				
			||||||
	int			rq_splice_ok;   /* turned off in gss privacy
 | 
						int			rq_splice_ok;   /* turned off in gss privacy
 | 
				
			||||||
						 * to prevent encrypting page
 | 
											 * to prevent encrypting page
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -744,6 +744,13 @@ static struct pf_desc gss_kerberos_pfs[] = {
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MODULE_ALIAS("rpc-auth-gss-krb5");
 | 
				
			||||||
 | 
					MODULE_ALIAS("rpc-auth-gss-krb5i");
 | 
				
			||||||
 | 
					MODULE_ALIAS("rpc-auth-gss-krb5p");
 | 
				
			||||||
 | 
					MODULE_ALIAS("rpc-auth-gss-390003");
 | 
				
			||||||
 | 
					MODULE_ALIAS("rpc-auth-gss-390004");
 | 
				
			||||||
 | 
					MODULE_ALIAS("rpc-auth-gss-390005");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct gss_api_mech gss_kerberos_mech = {
 | 
					static struct gss_api_mech gss_kerberos_mech = {
 | 
				
			||||||
	.gm_name	= "krb5",
 | 
						.gm_name	= "krb5",
 | 
				
			||||||
	.gm_owner	= THIS_MODULE,
 | 
						.gm_owner	= THIS_MODULE,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,7 +141,7 @@ gss_mech_get(struct gss_api_mech *gm)
 | 
				
			||||||
EXPORT_SYMBOL_GPL(gss_mech_get);
 | 
					EXPORT_SYMBOL_GPL(gss_mech_get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gss_api_mech *
 | 
					struct gss_api_mech *
 | 
				
			||||||
gss_mech_get_by_name(const char *name)
 | 
					_gss_mech_get_by_name(const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct gss_api_mech	*pos, *gm = NULL;
 | 
						struct gss_api_mech	*pos, *gm = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,6 +158,17 @@ gss_mech_get_by_name(const char *name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gss_api_mech * gss_mech_get_by_name(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gss_api_mech *gm = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gm = _gss_mech_get_by_name(name);
 | 
				
			||||||
 | 
						if (!gm) {
 | 
				
			||||||
 | 
							request_module("rpc-auth-gss-%s", name);
 | 
				
			||||||
 | 
							gm = _gss_mech_get_by_name(name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return gm;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
 | 
					EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gss_api_mech *
 | 
					struct gss_api_mech *
 | 
				
			||||||
| 
						 | 
					@ -194,10 +205,9 @@ mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gss_api_mech *
 | 
					struct gss_api_mech *_gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 | 
				
			||||||
gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct gss_api_mech *pos, *gm = NULL;
 | 
						struct gss_api_mech *gm = NULL, *pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(®istered_mechs_lock);
 | 
						spin_lock(®istered_mechs_lock);
 | 
				
			||||||
	list_for_each_entry(pos, ®istered_mechs, gm_list) {
 | 
						list_for_each_entry(pos, ®istered_mechs, gm_list) {
 | 
				
			||||||
| 
						 | 
					@ -213,6 +223,20 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 | 
				
			||||||
	return gm;
 | 
						return gm;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gss_api_mech *
 | 
				
			||||||
 | 
					gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct gss_api_mech *gm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gm = _gss_mech_get_by_pseudoflavor(pseudoflavor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!gm) {
 | 
				
			||||||
 | 
							request_module("rpc-auth-gss-%u", pseudoflavor);
 | 
				
			||||||
 | 
							gm = _gss_mech_get_by_pseudoflavor(pseudoflavor);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return gm;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
 | 
					EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr)
 | 
					int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -902,12 +902,13 @@ void svc_delete_xprt(struct svc_xprt *xprt)
 | 
				
			||||||
	if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags))
 | 
						if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags))
 | 
				
			||||||
		list_del_init(&xprt->xpt_list);
 | 
							list_del_init(&xprt->xpt_list);
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We used to delete the transport from whichever list
 | 
						 * The only time we're called while xpt_ready is still on a list
 | 
				
			||||||
	 * it's sk_xprt.xpt_ready node was on, but we don't actually
 | 
						 * is while the list itself is about to be destroyed (in
 | 
				
			||||||
	 * need to.  This is because the only time we're called
 | 
						 * svc_destroy).  BUT svc_xprt_enqueue could still be attempting
 | 
				
			||||||
	 * while still attached to a queue, the queue itself
 | 
						 * to add new entries to the sp_sockets list, so we can't leave
 | 
				
			||||||
	 * is about to be destroyed (in svc_destroy).
 | 
						 * a freed xprt on it.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						list_del_init(&xprt->xpt_ready);
 | 
				
			||||||
	if (test_bit(XPT_TEMP, &xprt->xpt_flags))
 | 
						if (test_bit(XPT_TEMP, &xprt->xpt_flags))
 | 
				
			||||||
		serv->sv_tmpcnt--;
 | 
							serv->sv_tmpcnt--;
 | 
				
			||||||
	spin_unlock_bh(&serv->sv_lock);
 | 
						spin_unlock_bh(&serv->sv_lock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,12 +30,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct unix_domain {
 | 
					struct unix_domain {
 | 
				
			||||||
	struct auth_domain	h;
 | 
						struct auth_domain	h;
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	int	addr_changes;
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
	/* other stuff later */
 | 
						/* other stuff later */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct auth_ops svcauth_null;
 | 
				
			||||||
extern struct auth_ops svcauth_unix;
 | 
					extern struct auth_ops svcauth_unix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void svcauth_unix_domain_release(struct auth_domain *dom)
 | 
					static void svcauth_unix_domain_release(struct auth_domain *dom)
 | 
				
			||||||
| 
						 | 
					@ -74,9 +72,6 @@ struct auth_domain *unix_domain_find(char *name)
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		new->h.flavour = &svcauth_unix;
 | 
							new->h.flavour = &svcauth_unix;
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
		new->addr_changes = 0;
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
		rv = auth_domain_lookup(name, &new->h);
 | 
							rv = auth_domain_lookup(name, &new->h);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -95,9 +90,6 @@ struct ip_map {
 | 
				
			||||||
	char			m_class[8]; /* e.g. "nfsd" */
 | 
						char			m_class[8]; /* e.g. "nfsd" */
 | 
				
			||||||
	struct in6_addr		m_addr;
 | 
						struct in6_addr		m_addr;
 | 
				
			||||||
	struct unix_domain	*m_client;
 | 
						struct unix_domain	*m_client;
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	int			m_add_change;
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ip_map_put(struct kref *kref)
 | 
					static void ip_map_put(struct kref *kref)
 | 
				
			||||||
| 
						 | 
					@ -151,9 +143,6 @@ static void update(struct cache_head *cnew, struct cache_head *citem)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kref_get(&item->m_client->h.ref);
 | 
						kref_get(&item->m_client->h.ref);
 | 
				
			||||||
	new->m_client = item->m_client;
 | 
						new->m_client = item->m_client;
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	new->m_add_change = item->m_add_change;
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static struct cache_head *ip_map_alloc(void)
 | 
					static struct cache_head *ip_map_alloc(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -338,16 +327,6 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
 | 
				
			||||||
	ip.h.flags = 0;
 | 
						ip.h.flags = 0;
 | 
				
			||||||
	if (!udom)
 | 
						if (!udom)
 | 
				
			||||||
		set_bit(CACHE_NEGATIVE, &ip.h.flags);
 | 
							set_bit(CACHE_NEGATIVE, &ip.h.flags);
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		ip.m_add_change = udom->addr_changes;
 | 
					 | 
				
			||||||
		/* if this is from the legacy set_client system call,
 | 
					 | 
				
			||||||
		 * we need m_add_change to be one higher
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		if (expiry == NEVER)
 | 
					 | 
				
			||||||
			ip.m_add_change++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
	ip.h.expiry_time = expiry;
 | 
						ip.h.expiry_time = expiry;
 | 
				
			||||||
	ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
 | 
						ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
 | 
				
			||||||
				 hash_str(ipm->m_class, IP_HASHBITS) ^
 | 
									 hash_str(ipm->m_class, IP_HASHBITS) ^
 | 
				
			||||||
| 
						 | 
					@ -367,62 +346,6 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm,
 | 
				
			||||||
	return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
 | 
						return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFSD_DEPRECATED
 | 
					 | 
				
			||||||
int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct unix_domain *udom;
 | 
					 | 
				
			||||||
	struct ip_map *ipmp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dom->flavour != &svcauth_unix)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	udom = container_of(dom, struct unix_domain, h);
 | 
					 | 
				
			||||||
	ipmp = ip_map_lookup(net, "nfsd", addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ipmp)
 | 
					 | 
				
			||||||
		return ip_map_update(net, ipmp, udom, NEVER);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
EXPORT_SYMBOL_GPL(auth_unix_add_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int auth_unix_forget_old(struct auth_domain *dom)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct unix_domain *udom;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dom->flavour != &svcauth_unix)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	udom = container_of(dom, struct unix_domain, h);
 | 
					 | 
				
			||||||
	udom->addr_changes++;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
EXPORT_SYMBOL_GPL(auth_unix_forget_old);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ip_map *ipm;
 | 
					 | 
				
			||||||
	struct auth_domain *rv;
 | 
					 | 
				
			||||||
	struct sunrpc_net *sn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sn = net_generic(net, sunrpc_net_id);
 | 
					 | 
				
			||||||
	ipm = ip_map_lookup(net, "nfsd", addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!ipm)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
 | 
					 | 
				
			||||||
		sunrpc_invalidate(&ipm->h, sn->ip_map_cache);
 | 
					 | 
				
			||||||
		rv = NULL;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		rv = &ipm->m_client->h;
 | 
					 | 
				
			||||||
		kref_get(&rv->ref);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cache_put(&ipm->h, sn->ip_map_cache);
 | 
					 | 
				
			||||||
	return rv;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
EXPORT_SYMBOL_GPL(auth_unix_lookup);
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFSD_DEPRECATED */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void svcauth_unix_purge(void)
 | 
					void svcauth_unix_purge(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,8 @@
 | 
				
			||||||
#include <linux/sunrpc/stats.h>
 | 
					#include <linux/sunrpc/stats.h>
 | 
				
			||||||
#include <linux/sunrpc/xprt.h>
 | 
					#include <linux/sunrpc/xprt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sunrpc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 | 
					#define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue