Commit 797a9d797f8483bb67f265c761b76dcd5a077a23

Authored by Jeff Layton
Committed by J. Bruce Fields
1 parent 4ca1f872cd

nfsd: only register cld pipe notifier when CONFIG_NFSD_V4 is enabled

Otherwise, we get a warning or error similar to this when building with
CONFIG_NFSD_V4 disabled:

    ERROR: "nfsd4_cld_block" [fs/nfsd/nfsd.ko] undefined!

Fix this by wrapping the calls to rpc_pipefs_notifier_register and
..._unregister in another function and providing no-op replacements
when CONFIG_NFSD_V4 is disabled.

Reported-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

Showing 4 changed files with 21 additions and 5 deletions Inline Diff

1 /* 1 /*
2 * per net namespace data structures for nfsd 2 * per net namespace data structures for nfsd
3 * 3 *
4 * Copyright (C) 2012, Jeff Layton <jlayton@redhat.com> 4 * Copyright (C) 2012, Jeff Layton <jlayton@redhat.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free 7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option) 8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version. 9 * any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details. 14 * more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License along with 16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 51 17 * this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */ 19 */
20 20
21 #ifndef __NFSD_NETNS_H__ 21 #ifndef __NFSD_NETNS_H__
22 #define __NFSD_NETNS_H__ 22 #define __NFSD_NETNS_H__
23 23
24 #include <net/net_namespace.h> 24 #include <net/net_namespace.h>
25 #include <net/netns/generic.h> 25 #include <net/netns/generic.h>
26 26
27 struct cld_net; 27 struct cld_net;
28 28
29 struct nfsd_net { 29 struct nfsd_net {
30 struct cld_net *cld_net; 30 struct cld_net *cld_net;
31 }; 31 };
32 32
33 extern int nfsd_net_id; 33 extern int nfsd_net_id;
34 extern struct notifier_block nfsd4_cld_block;
35 #endif /* __NFSD_NETNS_H__ */ 34 #endif /* __NFSD_NETNS_H__ */
36 35
fs/nfsd/nfs4recover.c
1 /* 1 /*
2 * Copyright (c) 2004 The Regents of the University of Michigan. 2 * Copyright (c) 2004 The Regents of the University of Michigan.
3 * Copyright (c) 2012 Jeff Layton <jlayton@redhat.com> 3 * Copyright (c) 2012 Jeff Layton <jlayton@redhat.com>
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * Andy Adamson <andros@citi.umich.edu> 6 * Andy Adamson <andros@citi.umich.edu>
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 11 *
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its 17 * 3. Neither the name of the University nor the names of its
18 * contributors may be used to endorse or promote products derived 18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission. 19 * from this software without specific prior written permission.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * 32 *
33 */ 33 */
34 34
35 #include <linux/file.h> 35 #include <linux/file.h>
36 #include <linux/slab.h> 36 #include <linux/slab.h>
37 #include <linux/namei.h> 37 #include <linux/namei.h>
38 #include <linux/crypto.h> 38 #include <linux/crypto.h>
39 #include <linux/sched.h> 39 #include <linux/sched.h>
40 #include <linux/fs.h> 40 #include <linux/fs.h>
41 #include <linux/module.h> 41 #include <linux/module.h>
42 #include <net/net_namespace.h> 42 #include <net/net_namespace.h>
43 #include <linux/sunrpc/rpc_pipe_fs.h> 43 #include <linux/sunrpc/rpc_pipe_fs.h>
44 #include <linux/sunrpc/clnt.h> 44 #include <linux/sunrpc/clnt.h>
45 #include <linux/nfsd/cld.h> 45 #include <linux/nfsd/cld.h>
46 46
47 #include "nfsd.h" 47 #include "nfsd.h"
48 #include "state.h" 48 #include "state.h"
49 #include "vfs.h" 49 #include "vfs.h"
50 #include "netns.h" 50 #include "netns.h"
51 51
52 #define NFSDDBG_FACILITY NFSDDBG_PROC 52 #define NFSDDBG_FACILITY NFSDDBG_PROC
53 53
54 /* Declarations */ 54 /* Declarations */
55 struct nfsd4_client_tracking_ops { 55 struct nfsd4_client_tracking_ops {
56 int (*init)(struct net *); 56 int (*init)(struct net *);
57 void (*exit)(struct net *); 57 void (*exit)(struct net *);
58 void (*create)(struct nfs4_client *); 58 void (*create)(struct nfs4_client *);
59 void (*remove)(struct nfs4_client *); 59 void (*remove)(struct nfs4_client *);
60 int (*check)(struct nfs4_client *); 60 int (*check)(struct nfs4_client *);
61 void (*grace_done)(struct net *, time_t); 61 void (*grace_done)(struct net *, time_t);
62 }; 62 };
63 63
64 /* Globals */ 64 /* Globals */
65 static struct file *rec_file; 65 static struct file *rec_file;
66 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 66 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
67 static struct nfsd4_client_tracking_ops *client_tracking_ops; 67 static struct nfsd4_client_tracking_ops *client_tracking_ops;
68 68
69 static int 69 static int
70 nfs4_save_creds(const struct cred **original_creds) 70 nfs4_save_creds(const struct cred **original_creds)
71 { 71 {
72 struct cred *new; 72 struct cred *new;
73 73
74 new = prepare_creds(); 74 new = prepare_creds();
75 if (!new) 75 if (!new)
76 return -ENOMEM; 76 return -ENOMEM;
77 77
78 new->fsuid = 0; 78 new->fsuid = 0;
79 new->fsgid = 0; 79 new->fsgid = 0;
80 *original_creds = override_creds(new); 80 *original_creds = override_creds(new);
81 put_cred(new); 81 put_cred(new);
82 return 0; 82 return 0;
83 } 83 }
84 84
85 static void 85 static void
86 nfs4_reset_creds(const struct cred *original) 86 nfs4_reset_creds(const struct cred *original)
87 { 87 {
88 revert_creds(original); 88 revert_creds(original);
89 } 89 }
90 90
91 static void 91 static void
92 md5_to_hex(char *out, char *md5) 92 md5_to_hex(char *out, char *md5)
93 { 93 {
94 int i; 94 int i;
95 95
96 for (i=0; i<16; i++) { 96 for (i=0; i<16; i++) {
97 unsigned char c = md5[i]; 97 unsigned char c = md5[i];
98 98
99 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); 99 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
100 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); 100 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
101 } 101 }
102 *out = '\0'; 102 *out = '\0';
103 } 103 }
104 104
105 __be32 105 __be32
106 nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) 106 nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
107 { 107 {
108 struct xdr_netobj cksum; 108 struct xdr_netobj cksum;
109 struct hash_desc desc; 109 struct hash_desc desc;
110 struct scatterlist sg; 110 struct scatterlist sg;
111 __be32 status = nfserr_jukebox; 111 __be32 status = nfserr_jukebox;
112 112
113 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 113 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
114 clname->len, clname->data); 114 clname->len, clname->data);
115 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; 115 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
116 desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); 116 desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
117 if (IS_ERR(desc.tfm)) 117 if (IS_ERR(desc.tfm))
118 goto out_no_tfm; 118 goto out_no_tfm;
119 cksum.len = crypto_hash_digestsize(desc.tfm); 119 cksum.len = crypto_hash_digestsize(desc.tfm);
120 cksum.data = kmalloc(cksum.len, GFP_KERNEL); 120 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
121 if (cksum.data == NULL) 121 if (cksum.data == NULL)
122 goto out; 122 goto out;
123 123
124 sg_init_one(&sg, clname->data, clname->len); 124 sg_init_one(&sg, clname->data, clname->len);
125 125
126 if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data)) 126 if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data))
127 goto out; 127 goto out;
128 128
129 md5_to_hex(dname, cksum.data); 129 md5_to_hex(dname, cksum.data);
130 130
131 status = nfs_ok; 131 status = nfs_ok;
132 out: 132 out:
133 kfree(cksum.data); 133 kfree(cksum.data);
134 crypto_free_hash(desc.tfm); 134 crypto_free_hash(desc.tfm);
135 out_no_tfm: 135 out_no_tfm:
136 return status; 136 return status;
137 } 137 }
138 138
139 static void 139 static void
140 nfsd4_create_clid_dir(struct nfs4_client *clp) 140 nfsd4_create_clid_dir(struct nfs4_client *clp)
141 { 141 {
142 const struct cred *original_cred; 142 const struct cred *original_cred;
143 char *dname = clp->cl_recdir; 143 char *dname = clp->cl_recdir;
144 struct dentry *dir, *dentry; 144 struct dentry *dir, *dentry;
145 int status; 145 int status;
146 146
147 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); 147 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
148 148
149 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 149 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
150 return; 150 return;
151 if (!rec_file) 151 if (!rec_file)
152 return; 152 return;
153 status = nfs4_save_creds(&original_cred); 153 status = nfs4_save_creds(&original_cred);
154 if (status < 0) 154 if (status < 0)
155 return; 155 return;
156 156
157 dir = rec_file->f_path.dentry; 157 dir = rec_file->f_path.dentry;
158 /* lock the parent */ 158 /* lock the parent */
159 mutex_lock(&dir->d_inode->i_mutex); 159 mutex_lock(&dir->d_inode->i_mutex);
160 160
161 dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1); 161 dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1);
162 if (IS_ERR(dentry)) { 162 if (IS_ERR(dentry)) {
163 status = PTR_ERR(dentry); 163 status = PTR_ERR(dentry);
164 goto out_unlock; 164 goto out_unlock;
165 } 165 }
166 if (dentry->d_inode) 166 if (dentry->d_inode)
167 /* 167 /*
168 * In the 4.1 case, where we're called from 168 * In the 4.1 case, where we're called from
169 * reclaim_complete(), records from the previous reboot 169 * reclaim_complete(), records from the previous reboot
170 * may still be left, so this is OK. 170 * may still be left, so this is OK.
171 * 171 *
172 * In the 4.0 case, we should never get here; but we may 172 * In the 4.0 case, we should never get here; but we may
173 * as well be forgiving and just succeed silently. 173 * as well be forgiving and just succeed silently.
174 */ 174 */
175 goto out_put; 175 goto out_put;
176 status = mnt_want_write_file(rec_file); 176 status = mnt_want_write_file(rec_file);
177 if (status) 177 if (status)
178 goto out_put; 178 goto out_put;
179 status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); 179 status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU);
180 mnt_drop_write_file(rec_file); 180 mnt_drop_write_file(rec_file);
181 out_put: 181 out_put:
182 dput(dentry); 182 dput(dentry);
183 out_unlock: 183 out_unlock:
184 mutex_unlock(&dir->d_inode->i_mutex); 184 mutex_unlock(&dir->d_inode->i_mutex);
185 if (status == 0) 185 if (status == 0)
186 vfs_fsync(rec_file, 0); 186 vfs_fsync(rec_file, 0);
187 else 187 else
188 printk(KERN_ERR "NFSD: failed to write recovery record" 188 printk(KERN_ERR "NFSD: failed to write recovery record"
189 " (err %d); please check that %s exists" 189 " (err %d); please check that %s exists"
190 " and is writeable", status, 190 " and is writeable", status,
191 user_recovery_dirname); 191 user_recovery_dirname);
192 nfs4_reset_creds(original_cred); 192 nfs4_reset_creds(original_cred);
193 } 193 }
194 194
195 typedef int (recdir_func)(struct dentry *, struct dentry *); 195 typedef int (recdir_func)(struct dentry *, struct dentry *);
196 196
197 struct name_list { 197 struct name_list {
198 char name[HEXDIR_LEN]; 198 char name[HEXDIR_LEN];
199 struct list_head list; 199 struct list_head list;
200 }; 200 };
201 201
202 static int 202 static int
203 nfsd4_build_namelist(void *arg, const char *name, int namlen, 203 nfsd4_build_namelist(void *arg, const char *name, int namlen,
204 loff_t offset, u64 ino, unsigned int d_type) 204 loff_t offset, u64 ino, unsigned int d_type)
205 { 205 {
206 struct list_head *names = arg; 206 struct list_head *names = arg;
207 struct name_list *entry; 207 struct name_list *entry;
208 208
209 if (namlen != HEXDIR_LEN - 1) 209 if (namlen != HEXDIR_LEN - 1)
210 return 0; 210 return 0;
211 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL); 211 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
212 if (entry == NULL) 212 if (entry == NULL)
213 return -ENOMEM; 213 return -ENOMEM;
214 memcpy(entry->name, name, HEXDIR_LEN - 1); 214 memcpy(entry->name, name, HEXDIR_LEN - 1);
215 entry->name[HEXDIR_LEN - 1] = '\0'; 215 entry->name[HEXDIR_LEN - 1] = '\0';
216 list_add(&entry->list, names); 216 list_add(&entry->list, names);
217 return 0; 217 return 0;
218 } 218 }
219 219
220 static int 220 static int
221 nfsd4_list_rec_dir(recdir_func *f) 221 nfsd4_list_rec_dir(recdir_func *f)
222 { 222 {
223 const struct cred *original_cred; 223 const struct cred *original_cred;
224 struct dentry *dir = rec_file->f_path.dentry; 224 struct dentry *dir = rec_file->f_path.dentry;
225 LIST_HEAD(names); 225 LIST_HEAD(names);
226 int status; 226 int status;
227 227
228 status = nfs4_save_creds(&original_cred); 228 status = nfs4_save_creds(&original_cred);
229 if (status < 0) 229 if (status < 0)
230 return status; 230 return status;
231 231
232 status = vfs_llseek(rec_file, 0, SEEK_SET); 232 status = vfs_llseek(rec_file, 0, SEEK_SET);
233 if (status < 0) { 233 if (status < 0) {
234 nfs4_reset_creds(original_cred); 234 nfs4_reset_creds(original_cred);
235 return status; 235 return status;
236 } 236 }
237 237
238 status = vfs_readdir(rec_file, nfsd4_build_namelist, &names); 238 status = vfs_readdir(rec_file, nfsd4_build_namelist, &names);
239 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 239 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
240 while (!list_empty(&names)) { 240 while (!list_empty(&names)) {
241 struct name_list *entry; 241 struct name_list *entry;
242 entry = list_entry(names.next, struct name_list, list); 242 entry = list_entry(names.next, struct name_list, list);
243 if (!status) { 243 if (!status) {
244 struct dentry *dentry; 244 struct dentry *dentry;
245 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); 245 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
246 if (IS_ERR(dentry)) { 246 if (IS_ERR(dentry)) {
247 status = PTR_ERR(dentry); 247 status = PTR_ERR(dentry);
248 break; 248 break;
249 } 249 }
250 status = f(dir, dentry); 250 status = f(dir, dentry);
251 dput(dentry); 251 dput(dentry);
252 } 252 }
253 list_del(&entry->list); 253 list_del(&entry->list);
254 kfree(entry); 254 kfree(entry);
255 } 255 }
256 mutex_unlock(&dir->d_inode->i_mutex); 256 mutex_unlock(&dir->d_inode->i_mutex);
257 nfs4_reset_creds(original_cred); 257 nfs4_reset_creds(original_cred);
258 return status; 258 return status;
259 } 259 }
260 260
261 static int 261 static int
262 nfsd4_unlink_clid_dir(char *name, int namlen) 262 nfsd4_unlink_clid_dir(char *name, int namlen)
263 { 263 {
264 struct dentry *dir, *dentry; 264 struct dentry *dir, *dentry;
265 int status; 265 int status;
266 266
267 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 267 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
268 268
269 dir = rec_file->f_path.dentry; 269 dir = rec_file->f_path.dentry;
270 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 270 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
271 dentry = lookup_one_len(name, dir, namlen); 271 dentry = lookup_one_len(name, dir, namlen);
272 if (IS_ERR(dentry)) { 272 if (IS_ERR(dentry)) {
273 status = PTR_ERR(dentry); 273 status = PTR_ERR(dentry);
274 goto out_unlock; 274 goto out_unlock;
275 } 275 }
276 status = -ENOENT; 276 status = -ENOENT;
277 if (!dentry->d_inode) 277 if (!dentry->d_inode)
278 goto out; 278 goto out;
279 status = vfs_rmdir(dir->d_inode, dentry); 279 status = vfs_rmdir(dir->d_inode, dentry);
280 out: 280 out:
281 dput(dentry); 281 dput(dentry);
282 out_unlock: 282 out_unlock:
283 mutex_unlock(&dir->d_inode->i_mutex); 283 mutex_unlock(&dir->d_inode->i_mutex);
284 return status; 284 return status;
285 } 285 }
286 286
287 static void 287 static void
288 nfsd4_remove_clid_dir(struct nfs4_client *clp) 288 nfsd4_remove_clid_dir(struct nfs4_client *clp)
289 { 289 {
290 const struct cred *original_cred; 290 const struct cred *original_cred;
291 int status; 291 int status;
292 292
293 if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 293 if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
294 return; 294 return;
295 295
296 status = mnt_want_write_file(rec_file); 296 status = mnt_want_write_file(rec_file);
297 if (status) 297 if (status)
298 goto out; 298 goto out;
299 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 299 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
300 300
301 status = nfs4_save_creds(&original_cred); 301 status = nfs4_save_creds(&original_cred);
302 if (status < 0) 302 if (status < 0)
303 goto out; 303 goto out;
304 304
305 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); 305 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
306 nfs4_reset_creds(original_cred); 306 nfs4_reset_creds(original_cred);
307 if (status == 0) 307 if (status == 0)
308 vfs_fsync(rec_file, 0); 308 vfs_fsync(rec_file, 0);
309 mnt_drop_write_file(rec_file); 309 mnt_drop_write_file(rec_file);
310 out: 310 out:
311 if (status) 311 if (status)
312 printk("NFSD: Failed to remove expired client state directory" 312 printk("NFSD: Failed to remove expired client state directory"
313 " %.*s\n", HEXDIR_LEN, clp->cl_recdir); 313 " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
314 } 314 }
315 315
316 static int 316 static int
317 purge_old(struct dentry *parent, struct dentry *child) 317 purge_old(struct dentry *parent, struct dentry *child)
318 { 318 {
319 int status; 319 int status;
320 320
321 if (nfs4_has_reclaimed_state(child->d_name.name, false)) 321 if (nfs4_has_reclaimed_state(child->d_name.name, false))
322 return 0; 322 return 0;
323 323
324 status = vfs_rmdir(parent->d_inode, child); 324 status = vfs_rmdir(parent->d_inode, child);
325 if (status) 325 if (status)
326 printk("failed to remove client recovery directory %s\n", 326 printk("failed to remove client recovery directory %s\n",
327 child->d_name.name); 327 child->d_name.name);
328 /* Keep trying, success or failure: */ 328 /* Keep trying, success or failure: */
329 return 0; 329 return 0;
330 } 330 }
331 331
332 static void 332 static void
333 nfsd4_recdir_purge_old(struct net *net, time_t boot_time) 333 nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
334 { 334 {
335 int status; 335 int status;
336 336
337 if (!rec_file) 337 if (!rec_file)
338 return; 338 return;
339 status = mnt_want_write_file(rec_file); 339 status = mnt_want_write_file(rec_file);
340 if (status) 340 if (status)
341 goto out; 341 goto out;
342 status = nfsd4_list_rec_dir(purge_old); 342 status = nfsd4_list_rec_dir(purge_old);
343 if (status == 0) 343 if (status == 0)
344 vfs_fsync(rec_file, 0); 344 vfs_fsync(rec_file, 0);
345 mnt_drop_write_file(rec_file); 345 mnt_drop_write_file(rec_file);
346 out: 346 out:
347 if (status) 347 if (status)
348 printk("nfsd4: failed to purge old clients from recovery" 348 printk("nfsd4: failed to purge old clients from recovery"
349 " directory %s\n", rec_file->f_path.dentry->d_name.name); 349 " directory %s\n", rec_file->f_path.dentry->d_name.name);
350 } 350 }
351 351
352 static int 352 static int
353 load_recdir(struct dentry *parent, struct dentry *child) 353 load_recdir(struct dentry *parent, struct dentry *child)
354 { 354 {
355 if (child->d_name.len != HEXDIR_LEN - 1) { 355 if (child->d_name.len != HEXDIR_LEN - 1) {
356 printk("nfsd4: illegal name %s in recovery directory\n", 356 printk("nfsd4: illegal name %s in recovery directory\n",
357 child->d_name.name); 357 child->d_name.name);
358 /* Keep trying; maybe the others are OK: */ 358 /* Keep trying; maybe the others are OK: */
359 return 0; 359 return 0;
360 } 360 }
361 nfs4_client_to_reclaim(child->d_name.name); 361 nfs4_client_to_reclaim(child->d_name.name);
362 return 0; 362 return 0;
363 } 363 }
364 364
365 static int 365 static int
366 nfsd4_recdir_load(void) { 366 nfsd4_recdir_load(void) {
367 int status; 367 int status;
368 368
369 if (!rec_file) 369 if (!rec_file)
370 return 0; 370 return 0;
371 371
372 status = nfsd4_list_rec_dir(load_recdir); 372 status = nfsd4_list_rec_dir(load_recdir);
373 if (status) 373 if (status)
374 printk("nfsd4: failed loading clients from recovery" 374 printk("nfsd4: failed loading clients from recovery"
375 " directory %s\n", rec_file->f_path.dentry->d_name.name); 375 " directory %s\n", rec_file->f_path.dentry->d_name.name);
376 return status; 376 return status;
377 } 377 }
378 378
379 /* 379 /*
380 * Hold reference to the recovery directory. 380 * Hold reference to the recovery directory.
381 */ 381 */
382 382
383 static int 383 static int
384 nfsd4_init_recdir(void) 384 nfsd4_init_recdir(void)
385 { 385 {
386 const struct cred *original_cred; 386 const struct cred *original_cred;
387 int status; 387 int status;
388 388
389 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 389 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
390 user_recovery_dirname); 390 user_recovery_dirname);
391 391
392 BUG_ON(rec_file); 392 BUG_ON(rec_file);
393 393
394 status = nfs4_save_creds(&original_cred); 394 status = nfs4_save_creds(&original_cred);
395 if (status < 0) { 395 if (status < 0) {
396 printk("NFSD: Unable to change credentials to find recovery" 396 printk("NFSD: Unable to change credentials to find recovery"
397 " directory: error %d\n", 397 " directory: error %d\n",
398 status); 398 status);
399 return status; 399 return status;
400 } 400 }
401 401
402 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 402 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
403 if (IS_ERR(rec_file)) { 403 if (IS_ERR(rec_file)) {
404 printk("NFSD: unable to find recovery directory %s\n", 404 printk("NFSD: unable to find recovery directory %s\n",
405 user_recovery_dirname); 405 user_recovery_dirname);
406 status = PTR_ERR(rec_file); 406 status = PTR_ERR(rec_file);
407 rec_file = NULL; 407 rec_file = NULL;
408 } 408 }
409 409
410 nfs4_reset_creds(original_cred); 410 nfs4_reset_creds(original_cred);
411 return status; 411 return status;
412 } 412 }
413 413
414 static int 414 static int
415 nfsd4_load_reboot_recovery_data(struct net *net) 415 nfsd4_load_reboot_recovery_data(struct net *net)
416 { 416 {
417 int status; 417 int status;
418 418
419 /* XXX: The legacy code won't work in a container */ 419 /* XXX: The legacy code won't work in a container */
420 if (net != &init_net) { 420 if (net != &init_net) {
421 WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client " 421 WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client "
422 "tracking in a container!\n"); 422 "tracking in a container!\n");
423 return -EINVAL; 423 return -EINVAL;
424 } 424 }
425 425
426 nfs4_lock_state(); 426 nfs4_lock_state();
427 status = nfsd4_init_recdir(); 427 status = nfsd4_init_recdir();
428 if (!status) 428 if (!status)
429 status = nfsd4_recdir_load(); 429 status = nfsd4_recdir_load();
430 nfs4_unlock_state(); 430 nfs4_unlock_state();
431 if (status) 431 if (status)
432 printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n"); 432 printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
433 return status; 433 return status;
434 } 434 }
435 435
436 static void 436 static void
437 nfsd4_shutdown_recdir(void) 437 nfsd4_shutdown_recdir(void)
438 { 438 {
439 if (!rec_file) 439 if (!rec_file)
440 return; 440 return;
441 fput(rec_file); 441 fput(rec_file);
442 rec_file = NULL; 442 rec_file = NULL;
443 } 443 }
444 444
445 static void 445 static void
446 nfsd4_legacy_tracking_exit(struct net *net) 446 nfsd4_legacy_tracking_exit(struct net *net)
447 { 447 {
448 nfs4_release_reclaim(); 448 nfs4_release_reclaim();
449 nfsd4_shutdown_recdir(); 449 nfsd4_shutdown_recdir();
450 } 450 }
451 451
452 /* 452 /*
453 * Change the NFSv4 recovery directory to recdir. 453 * Change the NFSv4 recovery directory to recdir.
454 */ 454 */
455 int 455 int
456 nfs4_reset_recoverydir(char *recdir) 456 nfs4_reset_recoverydir(char *recdir)
457 { 457 {
458 int status; 458 int status;
459 struct path path; 459 struct path path;
460 460
461 status = kern_path(recdir, LOOKUP_FOLLOW, &path); 461 status = kern_path(recdir, LOOKUP_FOLLOW, &path);
462 if (status) 462 if (status)
463 return status; 463 return status;
464 status = -ENOTDIR; 464 status = -ENOTDIR;
465 if (S_ISDIR(path.dentry->d_inode->i_mode)) { 465 if (S_ISDIR(path.dentry->d_inode->i_mode)) {
466 strcpy(user_recovery_dirname, recdir); 466 strcpy(user_recovery_dirname, recdir);
467 status = 0; 467 status = 0;
468 } 468 }
469 path_put(&path); 469 path_put(&path);
470 return status; 470 return status;
471 } 471 }
472 472
473 char * 473 char *
474 nfs4_recoverydir(void) 474 nfs4_recoverydir(void)
475 { 475 {
476 return user_recovery_dirname; 476 return user_recovery_dirname;
477 } 477 }
478 478
479 static int 479 static int
480 nfsd4_check_legacy_client(struct nfs4_client *clp) 480 nfsd4_check_legacy_client(struct nfs4_client *clp)
481 { 481 {
482 /* did we already find that this client is stable? */ 482 /* did we already find that this client is stable? */
483 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 483 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
484 return 0; 484 return 0;
485 485
486 /* look for it in the reclaim hashtable otherwise */ 486 /* look for it in the reclaim hashtable otherwise */
487 if (nfsd4_find_reclaim_client(clp)) { 487 if (nfsd4_find_reclaim_client(clp)) {
488 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 488 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
489 return 0; 489 return 0;
490 } 490 }
491 491
492 return -ENOENT; 492 return -ENOENT;
493 } 493 }
494 494
495 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 495 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
496 .init = nfsd4_load_reboot_recovery_data, 496 .init = nfsd4_load_reboot_recovery_data,
497 .exit = nfsd4_legacy_tracking_exit, 497 .exit = nfsd4_legacy_tracking_exit,
498 .create = nfsd4_create_clid_dir, 498 .create = nfsd4_create_clid_dir,
499 .remove = nfsd4_remove_clid_dir, 499 .remove = nfsd4_remove_clid_dir,
500 .check = nfsd4_check_legacy_client, 500 .check = nfsd4_check_legacy_client,
501 .grace_done = nfsd4_recdir_purge_old, 501 .grace_done = nfsd4_recdir_purge_old,
502 }; 502 };
503 503
504 /* Globals */ 504 /* Globals */
505 #define NFSD_PIPE_DIR "nfsd" 505 #define NFSD_PIPE_DIR "nfsd"
506 #define NFSD_CLD_PIPE "cld" 506 #define NFSD_CLD_PIPE "cld"
507 507
508 /* per-net-ns structure for holding cld upcall info */ 508 /* per-net-ns structure for holding cld upcall info */
509 struct cld_net { 509 struct cld_net {
510 struct rpc_pipe *cn_pipe; 510 struct rpc_pipe *cn_pipe;
511 spinlock_t cn_lock; 511 spinlock_t cn_lock;
512 struct list_head cn_list; 512 struct list_head cn_list;
513 unsigned int cn_xid; 513 unsigned int cn_xid;
514 }; 514 };
515 515
516 struct cld_upcall { 516 struct cld_upcall {
517 struct list_head cu_list; 517 struct list_head cu_list;
518 struct cld_net *cu_net; 518 struct cld_net *cu_net;
519 struct task_struct *cu_task; 519 struct task_struct *cu_task;
520 struct cld_msg cu_msg; 520 struct cld_msg cu_msg;
521 }; 521 };
522 522
523 static int 523 static int
524 __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 524 __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
525 { 525 {
526 int ret; 526 int ret;
527 struct rpc_pipe_msg msg; 527 struct rpc_pipe_msg msg;
528 528
529 memset(&msg, 0, sizeof(msg)); 529 memset(&msg, 0, sizeof(msg));
530 msg.data = cmsg; 530 msg.data = cmsg;
531 msg.len = sizeof(*cmsg); 531 msg.len = sizeof(*cmsg);
532 532
533 /* 533 /*
534 * Set task state before we queue the upcall. That prevents 534 * Set task state before we queue the upcall. That prevents
535 * wake_up_process in the downcall from racing with schedule. 535 * wake_up_process in the downcall from racing with schedule.
536 */ 536 */
537 set_current_state(TASK_UNINTERRUPTIBLE); 537 set_current_state(TASK_UNINTERRUPTIBLE);
538 ret = rpc_queue_upcall(pipe, &msg); 538 ret = rpc_queue_upcall(pipe, &msg);
539 if (ret < 0) { 539 if (ret < 0) {
540 set_current_state(TASK_RUNNING); 540 set_current_state(TASK_RUNNING);
541 goto out; 541 goto out;
542 } 542 }
543 543
544 schedule(); 544 schedule();
545 set_current_state(TASK_RUNNING); 545 set_current_state(TASK_RUNNING);
546 546
547 if (msg.errno < 0) 547 if (msg.errno < 0)
548 ret = msg.errno; 548 ret = msg.errno;
549 out: 549 out:
550 return ret; 550 return ret;
551 } 551 }
552 552
553 static int 553 static int
554 cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 554 cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
555 { 555 {
556 int ret; 556 int ret;
557 557
558 /* 558 /*
559 * -EAGAIN occurs when pipe is closed and reopened while there are 559 * -EAGAIN occurs when pipe is closed and reopened while there are
560 * upcalls queued. 560 * upcalls queued.
561 */ 561 */
562 do { 562 do {
563 ret = __cld_pipe_upcall(pipe, cmsg); 563 ret = __cld_pipe_upcall(pipe, cmsg);
564 } while (ret == -EAGAIN); 564 } while (ret == -EAGAIN);
565 565
566 return ret; 566 return ret;
567 } 567 }
568 568
569 static ssize_t 569 static ssize_t
570 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 570 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
571 { 571 {
572 struct cld_upcall *tmp, *cup; 572 struct cld_upcall *tmp, *cup;
573 struct cld_msg *cmsg = (struct cld_msg *)src; 573 struct cld_msg *cmsg = (struct cld_msg *)src;
574 uint32_t xid; 574 uint32_t xid;
575 struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info, 575 struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info,
576 nfsd_net_id); 576 nfsd_net_id);
577 struct cld_net *cn = nn->cld_net; 577 struct cld_net *cn = nn->cld_net;
578 578
579 if (mlen != sizeof(*cmsg)) { 579 if (mlen != sizeof(*cmsg)) {
580 dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen, 580 dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen,
581 sizeof(*cmsg)); 581 sizeof(*cmsg));
582 return -EINVAL; 582 return -EINVAL;
583 } 583 }
584 584
585 /* copy just the xid so we can try to find that */ 585 /* copy just the xid so we can try to find that */
586 if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) { 586 if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) {
587 dprintk("%s: error when copying xid from userspace", __func__); 587 dprintk("%s: error when copying xid from userspace", __func__);
588 return -EFAULT; 588 return -EFAULT;
589 } 589 }
590 590
591 /* walk the list and find corresponding xid */ 591 /* walk the list and find corresponding xid */
592 cup = NULL; 592 cup = NULL;
593 spin_lock(&cn->cn_lock); 593 spin_lock(&cn->cn_lock);
594 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 594 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
595 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) { 595 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) {
596 cup = tmp; 596 cup = tmp;
597 list_del_init(&cup->cu_list); 597 list_del_init(&cup->cu_list);
598 break; 598 break;
599 } 599 }
600 } 600 }
601 spin_unlock(&cn->cn_lock); 601 spin_unlock(&cn->cn_lock);
602 602
603 /* couldn't find upcall? */ 603 /* couldn't find upcall? */
604 if (!cup) { 604 if (!cup) {
605 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); 605 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
606 return -EINVAL; 606 return -EINVAL;
607 } 607 }
608 608
609 if (copy_from_user(&cup->cu_msg, src, mlen) != 0) 609 if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
610 return -EFAULT; 610 return -EFAULT;
611 611
612 wake_up_process(cup->cu_task); 612 wake_up_process(cup->cu_task);
613 return mlen; 613 return mlen;
614 } 614 }
615 615
616 static void 616 static void
617 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) 617 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
618 { 618 {
619 struct cld_msg *cmsg = msg->data; 619 struct cld_msg *cmsg = msg->data;
620 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, 620 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
621 cu_msg); 621 cu_msg);
622 622
623 /* errno >= 0 means we got a downcall */ 623 /* errno >= 0 means we got a downcall */
624 if (msg->errno >= 0) 624 if (msg->errno >= 0)
625 return; 625 return;
626 626
627 wake_up_process(cup->cu_task); 627 wake_up_process(cup->cu_task);
628 } 628 }
629 629
630 static const struct rpc_pipe_ops cld_upcall_ops = { 630 static const struct rpc_pipe_ops cld_upcall_ops = {
631 .upcall = rpc_pipe_generic_upcall, 631 .upcall = rpc_pipe_generic_upcall,
632 .downcall = cld_pipe_downcall, 632 .downcall = cld_pipe_downcall,
633 .destroy_msg = cld_pipe_destroy_msg, 633 .destroy_msg = cld_pipe_destroy_msg,
634 }; 634 };
635 635
636 static struct dentry * 636 static struct dentry *
637 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) 637 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
638 { 638 {
639 struct dentry *dir, *dentry; 639 struct dentry *dir, *dentry;
640 640
641 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); 641 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
642 if (dir == NULL) 642 if (dir == NULL)
643 return ERR_PTR(-ENOENT); 643 return ERR_PTR(-ENOENT);
644 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); 644 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
645 dput(dir); 645 dput(dir);
646 return dentry; 646 return dentry;
647 } 647 }
648 648
649 static void 649 static void
650 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe) 650 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
651 { 651 {
652 if (pipe->dentry) 652 if (pipe->dentry)
653 rpc_unlink(pipe->dentry); 653 rpc_unlink(pipe->dentry);
654 } 654 }
655 655
656 static struct dentry * 656 static struct dentry *
657 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) 657 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
658 { 658 {
659 struct super_block *sb; 659 struct super_block *sb;
660 struct dentry *dentry; 660 struct dentry *dentry;
661 661
662 sb = rpc_get_sb_net(net); 662 sb = rpc_get_sb_net(net);
663 if (!sb) 663 if (!sb)
664 return NULL; 664 return NULL;
665 dentry = nfsd4_cld_register_sb(sb, pipe); 665 dentry = nfsd4_cld_register_sb(sb, pipe);
666 rpc_put_sb_net(net); 666 rpc_put_sb_net(net);
667 return dentry; 667 return dentry;
668 } 668 }
669 669
670 static void 670 static void
671 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) 671 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
672 { 672 {
673 struct super_block *sb; 673 struct super_block *sb;
674 674
675 sb = rpc_get_sb_net(net); 675 sb = rpc_get_sb_net(net);
676 if (sb) { 676 if (sb) {
677 nfsd4_cld_unregister_sb(pipe); 677 nfsd4_cld_unregister_sb(pipe);
678 rpc_put_sb_net(net); 678 rpc_put_sb_net(net);
679 } 679 }
680 } 680 }
681 681
682 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 682 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
683 static int 683 static int
684 nfsd4_init_cld_pipe(struct net *net) 684 nfsd4_init_cld_pipe(struct net *net)
685 { 685 {
686 int ret; 686 int ret;
687 struct dentry *dentry; 687 struct dentry *dentry;
688 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 688 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
689 struct cld_net *cn; 689 struct cld_net *cn;
690 690
691 if (nn->cld_net) 691 if (nn->cld_net)
692 return 0; 692 return 0;
693 693
694 cn = kzalloc(sizeof(*cn), GFP_KERNEL); 694 cn = kzalloc(sizeof(*cn), GFP_KERNEL);
695 if (!cn) { 695 if (!cn) {
696 ret = -ENOMEM; 696 ret = -ENOMEM;
697 goto err; 697 goto err;
698 } 698 }
699 699
700 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 700 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
701 if (IS_ERR(cn->cn_pipe)) { 701 if (IS_ERR(cn->cn_pipe)) {
702 ret = PTR_ERR(cn->cn_pipe); 702 ret = PTR_ERR(cn->cn_pipe);
703 goto err; 703 goto err;
704 } 704 }
705 spin_lock_init(&cn->cn_lock); 705 spin_lock_init(&cn->cn_lock);
706 INIT_LIST_HEAD(&cn->cn_list); 706 INIT_LIST_HEAD(&cn->cn_list);
707 707
708 dentry = nfsd4_cld_register_net(net, cn->cn_pipe); 708 dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
709 if (IS_ERR(dentry)) { 709 if (IS_ERR(dentry)) {
710 ret = PTR_ERR(dentry); 710 ret = PTR_ERR(dentry);
711 goto err_destroy_data; 711 goto err_destroy_data;
712 } 712 }
713 713
714 cn->cn_pipe->dentry = dentry; 714 cn->cn_pipe->dentry = dentry;
715 nn->cld_net = cn; 715 nn->cld_net = cn;
716 return 0; 716 return 0;
717 717
718 err_destroy_data: 718 err_destroy_data:
719 rpc_destroy_pipe_data(cn->cn_pipe); 719 rpc_destroy_pipe_data(cn->cn_pipe);
720 err: 720 err:
721 kfree(cn); 721 kfree(cn);
722 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 722 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
723 ret); 723 ret);
724 return ret; 724 return ret;
725 } 725 }
726 726
727 static void 727 static void
728 nfsd4_remove_cld_pipe(struct net *net) 728 nfsd4_remove_cld_pipe(struct net *net)
729 { 729 {
730 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 730 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
731 struct cld_net *cn = nn->cld_net; 731 struct cld_net *cn = nn->cld_net;
732 732
733 nfsd4_cld_unregister_net(net, cn->cn_pipe); 733 nfsd4_cld_unregister_net(net, cn->cn_pipe);
734 rpc_destroy_pipe_data(cn->cn_pipe); 734 rpc_destroy_pipe_data(cn->cn_pipe);
735 kfree(nn->cld_net); 735 kfree(nn->cld_net);
736 nn->cld_net = NULL; 736 nn->cld_net = NULL;
737 } 737 }
738 738
739 static struct cld_upcall * 739 static struct cld_upcall *
740 alloc_cld_upcall(struct cld_net *cn) 740 alloc_cld_upcall(struct cld_net *cn)
741 { 741 {
742 struct cld_upcall *new, *tmp; 742 struct cld_upcall *new, *tmp;
743 743
744 new = kzalloc(sizeof(*new), GFP_KERNEL); 744 new = kzalloc(sizeof(*new), GFP_KERNEL);
745 if (!new) 745 if (!new)
746 return new; 746 return new;
747 747
748 /* FIXME: hard cap on number in flight? */ 748 /* FIXME: hard cap on number in flight? */
749 restart_search: 749 restart_search:
750 spin_lock(&cn->cn_lock); 750 spin_lock(&cn->cn_lock);
751 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 751 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
752 if (tmp->cu_msg.cm_xid == cn->cn_xid) { 752 if (tmp->cu_msg.cm_xid == cn->cn_xid) {
753 cn->cn_xid++; 753 cn->cn_xid++;
754 spin_unlock(&cn->cn_lock); 754 spin_unlock(&cn->cn_lock);
755 goto restart_search; 755 goto restart_search;
756 } 756 }
757 } 757 }
758 new->cu_task = current; 758 new->cu_task = current;
759 new->cu_msg.cm_vers = CLD_UPCALL_VERSION; 759 new->cu_msg.cm_vers = CLD_UPCALL_VERSION;
760 put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid); 760 put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid);
761 new->cu_net = cn; 761 new->cu_net = cn;
762 list_add(&new->cu_list, &cn->cn_list); 762 list_add(&new->cu_list, &cn->cn_list);
763 spin_unlock(&cn->cn_lock); 763 spin_unlock(&cn->cn_lock);
764 764
765 dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid); 765 dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid);
766 766
767 return new; 767 return new;
768 } 768 }
769 769
770 static void 770 static void
771 free_cld_upcall(struct cld_upcall *victim) 771 free_cld_upcall(struct cld_upcall *victim)
772 { 772 {
773 struct cld_net *cn = victim->cu_net; 773 struct cld_net *cn = victim->cu_net;
774 774
775 spin_lock(&cn->cn_lock); 775 spin_lock(&cn->cn_lock);
776 list_del(&victim->cu_list); 776 list_del(&victim->cu_list);
777 spin_unlock(&cn->cn_lock); 777 spin_unlock(&cn->cn_lock);
778 kfree(victim); 778 kfree(victim);
779 } 779 }
780 780
781 /* Ask daemon to create a new record */ 781 /* Ask daemon to create a new record */
782 static void 782 static void
783 nfsd4_cld_create(struct nfs4_client *clp) 783 nfsd4_cld_create(struct nfs4_client *clp)
784 { 784 {
785 int ret; 785 int ret;
786 struct cld_upcall *cup; 786 struct cld_upcall *cup;
787 /* FIXME: determine net from clp */ 787 /* FIXME: determine net from clp */
788 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 788 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
789 struct cld_net *cn = nn->cld_net; 789 struct cld_net *cn = nn->cld_net;
790 790
791 /* Don't upcall if it's already stored */ 791 /* Don't upcall if it's already stored */
792 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 792 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
793 return; 793 return;
794 794
795 cup = alloc_cld_upcall(cn); 795 cup = alloc_cld_upcall(cn);
796 if (!cup) { 796 if (!cup) {
797 ret = -ENOMEM; 797 ret = -ENOMEM;
798 goto out_err; 798 goto out_err;
799 } 799 }
800 800
801 cup->cu_msg.cm_cmd = Cld_Create; 801 cup->cu_msg.cm_cmd = Cld_Create;
802 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 802 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
803 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 803 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
804 clp->cl_name.len); 804 clp->cl_name.len);
805 805
806 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 806 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
807 if (!ret) { 807 if (!ret) {
808 ret = cup->cu_msg.cm_status; 808 ret = cup->cu_msg.cm_status;
809 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 809 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
810 } 810 }
811 811
812 free_cld_upcall(cup); 812 free_cld_upcall(cup);
813 out_err: 813 out_err:
814 if (ret) 814 if (ret)
815 printk(KERN_ERR "NFSD: Unable to create client " 815 printk(KERN_ERR "NFSD: Unable to create client "
816 "record on stable storage: %d\n", ret); 816 "record on stable storage: %d\n", ret);
817 } 817 }
818 818
819 /* Ask daemon to create a new record */ 819 /* Ask daemon to create a new record */
820 static void 820 static void
821 nfsd4_cld_remove(struct nfs4_client *clp) 821 nfsd4_cld_remove(struct nfs4_client *clp)
822 { 822 {
823 int ret; 823 int ret;
824 struct cld_upcall *cup; 824 struct cld_upcall *cup;
825 /* FIXME: determine net from clp */ 825 /* FIXME: determine net from clp */
826 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 826 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
827 struct cld_net *cn = nn->cld_net; 827 struct cld_net *cn = nn->cld_net;
828 828
829 /* Don't upcall if it's already removed */ 829 /* Don't upcall if it's already removed */
830 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 830 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
831 return; 831 return;
832 832
833 cup = alloc_cld_upcall(cn); 833 cup = alloc_cld_upcall(cn);
834 if (!cup) { 834 if (!cup) {
835 ret = -ENOMEM; 835 ret = -ENOMEM;
836 goto out_err; 836 goto out_err;
837 } 837 }
838 838
839 cup->cu_msg.cm_cmd = Cld_Remove; 839 cup->cu_msg.cm_cmd = Cld_Remove;
840 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 840 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
841 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 841 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
842 clp->cl_name.len); 842 clp->cl_name.len);
843 843
844 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 844 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
845 if (!ret) { 845 if (!ret) {
846 ret = cup->cu_msg.cm_status; 846 ret = cup->cu_msg.cm_status;
847 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 847 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
848 } 848 }
849 849
850 free_cld_upcall(cup); 850 free_cld_upcall(cup);
851 out_err: 851 out_err:
852 if (ret) 852 if (ret)
853 printk(KERN_ERR "NFSD: Unable to remove client " 853 printk(KERN_ERR "NFSD: Unable to remove client "
854 "record from stable storage: %d\n", ret); 854 "record from stable storage: %d\n", ret);
855 } 855 }
856 856
857 /* Check for presence of a record, and update its timestamp */ 857 /* Check for presence of a record, and update its timestamp */
858 static int 858 static int
859 nfsd4_cld_check(struct nfs4_client *clp) 859 nfsd4_cld_check(struct nfs4_client *clp)
860 { 860 {
861 int ret; 861 int ret;
862 struct cld_upcall *cup; 862 struct cld_upcall *cup;
863 /* FIXME: determine net from clp */ 863 /* FIXME: determine net from clp */
864 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 864 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
865 struct cld_net *cn = nn->cld_net; 865 struct cld_net *cn = nn->cld_net;
866 866
867 /* Don't upcall if one was already stored during this grace pd */ 867 /* Don't upcall if one was already stored during this grace pd */
868 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 868 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
869 return 0; 869 return 0;
870 870
871 cup = alloc_cld_upcall(cn); 871 cup = alloc_cld_upcall(cn);
872 if (!cup) { 872 if (!cup) {
873 printk(KERN_ERR "NFSD: Unable to check client record on " 873 printk(KERN_ERR "NFSD: Unable to check client record on "
874 "stable storage: %d\n", -ENOMEM); 874 "stable storage: %d\n", -ENOMEM);
875 return -ENOMEM; 875 return -ENOMEM;
876 } 876 }
877 877
878 cup->cu_msg.cm_cmd = Cld_Check; 878 cup->cu_msg.cm_cmd = Cld_Check;
879 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 879 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
880 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 880 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
881 clp->cl_name.len); 881 clp->cl_name.len);
882 882
883 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 883 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
884 if (!ret) { 884 if (!ret) {
885 ret = cup->cu_msg.cm_status; 885 ret = cup->cu_msg.cm_status;
886 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 886 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
887 } 887 }
888 888
889 free_cld_upcall(cup); 889 free_cld_upcall(cup);
890 return ret; 890 return ret;
891 } 891 }
892 892
893 static void 893 static void
894 nfsd4_cld_grace_done(struct net *net, time_t boot_time) 894 nfsd4_cld_grace_done(struct net *net, time_t boot_time)
895 { 895 {
896 int ret; 896 int ret;
897 struct cld_upcall *cup; 897 struct cld_upcall *cup;
898 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 898 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
899 struct cld_net *cn = nn->cld_net; 899 struct cld_net *cn = nn->cld_net;
900 900
901 cup = alloc_cld_upcall(cn); 901 cup = alloc_cld_upcall(cn);
902 if (!cup) { 902 if (!cup) {
903 ret = -ENOMEM; 903 ret = -ENOMEM;
904 goto out_err; 904 goto out_err;
905 } 905 }
906 906
907 cup->cu_msg.cm_cmd = Cld_GraceDone; 907 cup->cu_msg.cm_cmd = Cld_GraceDone;
908 cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time; 908 cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time;
909 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 909 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
910 if (!ret) 910 if (!ret)
911 ret = cup->cu_msg.cm_status; 911 ret = cup->cu_msg.cm_status;
912 912
913 free_cld_upcall(cup); 913 free_cld_upcall(cup);
914 out_err: 914 out_err:
915 if (ret) 915 if (ret)
916 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 916 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
917 } 917 }
918 918
919 static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 919 static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
920 .init = nfsd4_init_cld_pipe, 920 .init = nfsd4_init_cld_pipe,
921 .exit = nfsd4_remove_cld_pipe, 921 .exit = nfsd4_remove_cld_pipe,
922 .create = nfsd4_cld_create, 922 .create = nfsd4_cld_create,
923 .remove = nfsd4_cld_remove, 923 .remove = nfsd4_cld_remove,
924 .check = nfsd4_cld_check, 924 .check = nfsd4_cld_check,
925 .grace_done = nfsd4_cld_grace_done, 925 .grace_done = nfsd4_cld_grace_done,
926 }; 926 };
927 927
928 int 928 int
929 nfsd4_client_tracking_init(struct net *net) 929 nfsd4_client_tracking_init(struct net *net)
930 { 930 {
931 int status; 931 int status;
932 struct path path; 932 struct path path;
933 933
934 if (!client_tracking_ops) { 934 if (!client_tracking_ops) {
935 client_tracking_ops = &nfsd4_cld_tracking_ops; 935 client_tracking_ops = &nfsd4_cld_tracking_ops;
936 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 936 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
937 if (!status) { 937 if (!status) {
938 if (S_ISDIR(path.dentry->d_inode->i_mode)) 938 if (S_ISDIR(path.dentry->d_inode->i_mode))
939 client_tracking_ops = 939 client_tracking_ops =
940 &nfsd4_legacy_tracking_ops; 940 &nfsd4_legacy_tracking_ops;
941 path_put(&path); 941 path_put(&path);
942 } 942 }
943 } 943 }
944 944
945 status = client_tracking_ops->init(net); 945 status = client_tracking_ops->init(net);
946 if (status) { 946 if (status) {
947 printk(KERN_WARNING "NFSD: Unable to initialize client " 947 printk(KERN_WARNING "NFSD: Unable to initialize client "
948 "recovery tracking! (%d)\n", status); 948 "recovery tracking! (%d)\n", status);
949 client_tracking_ops = NULL; 949 client_tracking_ops = NULL;
950 } 950 }
951 return status; 951 return status;
952 } 952 }
953 953
954 void 954 void
955 nfsd4_client_tracking_exit(struct net *net) 955 nfsd4_client_tracking_exit(struct net *net)
956 { 956 {
957 if (client_tracking_ops) { 957 if (client_tracking_ops) {
958 client_tracking_ops->exit(net); 958 client_tracking_ops->exit(net);
959 client_tracking_ops = NULL; 959 client_tracking_ops = NULL;
960 } 960 }
961 } 961 }
962 962
963 void 963 void
964 nfsd4_client_record_create(struct nfs4_client *clp) 964 nfsd4_client_record_create(struct nfs4_client *clp)
965 { 965 {
966 if (client_tracking_ops) 966 if (client_tracking_ops)
967 client_tracking_ops->create(clp); 967 client_tracking_ops->create(clp);
968 } 968 }
969 969
970 void 970 void
971 nfsd4_client_record_remove(struct nfs4_client *clp) 971 nfsd4_client_record_remove(struct nfs4_client *clp)
972 { 972 {
973 if (client_tracking_ops) 973 if (client_tracking_ops)
974 client_tracking_ops->remove(clp); 974 client_tracking_ops->remove(clp);
975 } 975 }
976 976
977 int 977 int
978 nfsd4_client_record_check(struct nfs4_client *clp) 978 nfsd4_client_record_check(struct nfs4_client *clp)
979 { 979 {
980 if (client_tracking_ops) 980 if (client_tracking_ops)
981 return client_tracking_ops->check(clp); 981 return client_tracking_ops->check(clp);
982 982
983 return -EOPNOTSUPP; 983 return -EOPNOTSUPP;
984 } 984 }
985 985
986 void 986 void
987 nfsd4_record_grace_done(struct net *net, time_t boot_time) 987 nfsd4_record_grace_done(struct net *net, time_t boot_time)
988 { 988 {
989 if (client_tracking_ops) 989 if (client_tracking_ops)
990 client_tracking_ops->grace_done(net, boot_time); 990 client_tracking_ops->grace_done(net, boot_time);
991 } 991 }
992 992
993 static int 993 static int
994 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 994 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
995 { 995 {
996 struct super_block *sb = ptr; 996 struct super_block *sb = ptr;
997 struct net *net = sb->s_fs_info; 997 struct net *net = sb->s_fs_info;
998 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 998 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
999 struct cld_net *cn = nn->cld_net; 999 struct cld_net *cn = nn->cld_net;
1000 struct dentry *dentry; 1000 struct dentry *dentry;
1001 int ret = 0; 1001 int ret = 0;
1002 1002
1003 if (!try_module_get(THIS_MODULE)) 1003 if (!try_module_get(THIS_MODULE))
1004 return 0; 1004 return 0;
1005 1005
1006 if (!cn) { 1006 if (!cn) {
1007 module_put(THIS_MODULE); 1007 module_put(THIS_MODULE);
1008 return 0; 1008 return 0;
1009 } 1009 }
1010 1010
1011 switch (event) { 1011 switch (event) {
1012 case RPC_PIPEFS_MOUNT: 1012 case RPC_PIPEFS_MOUNT:
1013 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe); 1013 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
1014 if (IS_ERR(dentry)) { 1014 if (IS_ERR(dentry)) {
1015 ret = PTR_ERR(dentry); 1015 ret = PTR_ERR(dentry);
1016 break; 1016 break;
1017 } 1017 }
1018 cn->cn_pipe->dentry = dentry; 1018 cn->cn_pipe->dentry = dentry;
1019 break; 1019 break;
1020 case RPC_PIPEFS_UMOUNT: 1020 case RPC_PIPEFS_UMOUNT:
1021 if (cn->cn_pipe->dentry) 1021 if (cn->cn_pipe->dentry)
1022 nfsd4_cld_unregister_sb(cn->cn_pipe); 1022 nfsd4_cld_unregister_sb(cn->cn_pipe);
1023 break; 1023 break;
1024 default: 1024 default:
1025 ret = -ENOTSUPP; 1025 ret = -ENOTSUPP;
1026 break; 1026 break;
1027 } 1027 }
1028 module_put(THIS_MODULE); 1028 module_put(THIS_MODULE);
1029 return ret; 1029 return ret;
1030 } 1030 }
1031 1031
1032 struct notifier_block nfsd4_cld_block = { 1032 struct notifier_block nfsd4_cld_block = {
1033 .notifier_call = rpc_pipefs_event, 1033 .notifier_call = rpc_pipefs_event,
1034 }; 1034 };
1035
1036 int
1037 register_cld_notifier(void)
1038 {
1039 return rpc_pipefs_notifier_register(&nfsd4_cld_block);
1040 }
1041
1042 void
1043 unregister_cld_notifier(void)
1044 {
1045 rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
1046 }
1035 1047
1 /* 1 /*
2 * Syscall interface to knfsd. 2 * Syscall interface to knfsd.
3 * 3 *
4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
5 */ 5 */
6 6
7 #include <linux/slab.h> 7 #include <linux/slab.h>
8 #include <linux/namei.h> 8 #include <linux/namei.h>
9 #include <linux/ctype.h> 9 #include <linux/ctype.h>
10 10
11 #include <linux/sunrpc/svcsock.h> 11 #include <linux/sunrpc/svcsock.h>
12 #include <linux/lockd/lockd.h> 12 #include <linux/lockd/lockd.h>
13 #include <linux/sunrpc/clnt.h> 13 #include <linux/sunrpc/clnt.h>
14 #include <linux/sunrpc/gss_api.h> 14 #include <linux/sunrpc/gss_api.h>
15 #include <linux/sunrpc/gss_krb5_enctypes.h> 15 #include <linux/sunrpc/gss_krb5_enctypes.h>
16 #include <linux/sunrpc/rpc_pipe_fs.h> 16 #include <linux/sunrpc/rpc_pipe_fs.h>
17 #include <linux/module.h> 17 #include <linux/module.h>
18 18
19 #include "idmap.h" 19 #include "idmap.h"
20 #include "nfsd.h" 20 #include "nfsd.h"
21 #include "cache.h" 21 #include "cache.h"
22 #include "fault_inject.h" 22 #include "fault_inject.h"
23 #include "netns.h" 23 #include "netns.h"
24 24
25 /* 25 /*
26 * We have a single directory with several nodes in it. 26 * We have a single directory with several nodes in it.
27 */ 27 */
28 enum { 28 enum {
29 NFSD_Root = 1, 29 NFSD_Root = 1,
30 NFSD_List, 30 NFSD_List,
31 NFSD_Export_features, 31 NFSD_Export_features,
32 NFSD_Fh, 32 NFSD_Fh,
33 NFSD_FO_UnlockIP, 33 NFSD_FO_UnlockIP,
34 NFSD_FO_UnlockFS, 34 NFSD_FO_UnlockFS,
35 NFSD_Threads, 35 NFSD_Threads,
36 NFSD_Pool_Threads, 36 NFSD_Pool_Threads,
37 NFSD_Pool_Stats, 37 NFSD_Pool_Stats,
38 NFSD_Versions, 38 NFSD_Versions,
39 NFSD_Ports, 39 NFSD_Ports,
40 NFSD_MaxBlkSize, 40 NFSD_MaxBlkSize,
41 NFSD_SupportedEnctypes, 41 NFSD_SupportedEnctypes,
42 /* 42 /*
43 * The below MUST come last. Otherwise we leave a hole in nfsd_files[] 43 * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
44 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops 44 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
45 */ 45 */
46 #ifdef CONFIG_NFSD_V4 46 #ifdef CONFIG_NFSD_V4
47 NFSD_Leasetime, 47 NFSD_Leasetime,
48 NFSD_Gracetime, 48 NFSD_Gracetime,
49 NFSD_RecoveryDir, 49 NFSD_RecoveryDir,
50 #endif 50 #endif
51 }; 51 };
52 52
53 /* 53 /*
54 * write() for these nodes. 54 * write() for these nodes.
55 */ 55 */
56 static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 56 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
57 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size); 57 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
58 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size); 58 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
59 static ssize_t write_threads(struct file *file, char *buf, size_t size); 59 static ssize_t write_threads(struct file *file, char *buf, size_t size);
60 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); 60 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
61 static ssize_t write_versions(struct file *file, char *buf, size_t size); 61 static ssize_t write_versions(struct file *file, char *buf, size_t size);
62 static ssize_t write_ports(struct file *file, char *buf, size_t size); 62 static ssize_t write_ports(struct file *file, char *buf, size_t size);
63 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size); 63 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
64 #ifdef CONFIG_NFSD_V4 64 #ifdef CONFIG_NFSD_V4
65 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 65 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
66 static ssize_t write_gracetime(struct file *file, char *buf, size_t size); 66 static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
67 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 67 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
68 #endif 68 #endif
69 69
70 static ssize_t (*write_op[])(struct file *, char *, size_t) = { 70 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
71 [NFSD_Fh] = write_filehandle, 71 [NFSD_Fh] = write_filehandle,
72 [NFSD_FO_UnlockIP] = write_unlock_ip, 72 [NFSD_FO_UnlockIP] = write_unlock_ip,
73 [NFSD_FO_UnlockFS] = write_unlock_fs, 73 [NFSD_FO_UnlockFS] = write_unlock_fs,
74 [NFSD_Threads] = write_threads, 74 [NFSD_Threads] = write_threads,
75 [NFSD_Pool_Threads] = write_pool_threads, 75 [NFSD_Pool_Threads] = write_pool_threads,
76 [NFSD_Versions] = write_versions, 76 [NFSD_Versions] = write_versions,
77 [NFSD_Ports] = write_ports, 77 [NFSD_Ports] = write_ports,
78 [NFSD_MaxBlkSize] = write_maxblksize, 78 [NFSD_MaxBlkSize] = write_maxblksize,
79 #ifdef CONFIG_NFSD_V4 79 #ifdef CONFIG_NFSD_V4
80 [NFSD_Leasetime] = write_leasetime, 80 [NFSD_Leasetime] = write_leasetime,
81 [NFSD_Gracetime] = write_gracetime, 81 [NFSD_Gracetime] = write_gracetime,
82 [NFSD_RecoveryDir] = write_recoverydir, 82 [NFSD_RecoveryDir] = write_recoverydir,
83 #endif 83 #endif
84 }; 84 };
85 85
86 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) 86 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
87 { 87 {
88 ino_t ino = file->f_path.dentry->d_inode->i_ino; 88 ino_t ino = file->f_path.dentry->d_inode->i_ino;
89 char *data; 89 char *data;
90 ssize_t rv; 90 ssize_t rv;
91 91
92 if (ino >= ARRAY_SIZE(write_op) || !write_op[ino]) 92 if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
93 return -EINVAL; 93 return -EINVAL;
94 94
95 data = simple_transaction_get(file, buf, size); 95 data = simple_transaction_get(file, buf, size);
96 if (IS_ERR(data)) 96 if (IS_ERR(data))
97 return PTR_ERR(data); 97 return PTR_ERR(data);
98 98
99 rv = write_op[ino](file, data, size); 99 rv = write_op[ino](file, data, size);
100 if (rv >= 0) { 100 if (rv >= 0) {
101 simple_transaction_set(file, rv); 101 simple_transaction_set(file, rv);
102 rv = size; 102 rv = size;
103 } 103 }
104 return rv; 104 return rv;
105 } 105 }
106 106
107 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) 107 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
108 { 108 {
109 if (! file->private_data) { 109 if (! file->private_data) {
110 /* An attempt to read a transaction file without writing 110 /* An attempt to read a transaction file without writing
111 * causes a 0-byte write so that the file can return 111 * causes a 0-byte write so that the file can return
112 * state information 112 * state information
113 */ 113 */
114 ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos); 114 ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
115 if (rv < 0) 115 if (rv < 0)
116 return rv; 116 return rv;
117 } 117 }
118 return simple_transaction_read(file, buf, size, pos); 118 return simple_transaction_read(file, buf, size, pos);
119 } 119 }
120 120
121 static const struct file_operations transaction_ops = { 121 static const struct file_operations transaction_ops = {
122 .write = nfsctl_transaction_write, 122 .write = nfsctl_transaction_write,
123 .read = nfsctl_transaction_read, 123 .read = nfsctl_transaction_read,
124 .release = simple_transaction_release, 124 .release = simple_transaction_release,
125 .llseek = default_llseek, 125 .llseek = default_llseek,
126 }; 126 };
127 127
128 static int exports_open(struct inode *inode, struct file *file) 128 static int exports_open(struct inode *inode, struct file *file)
129 { 129 {
130 return seq_open(file, &nfs_exports_op); 130 return seq_open(file, &nfs_exports_op);
131 } 131 }
132 132
133 static const struct file_operations exports_operations = { 133 static const struct file_operations exports_operations = {
134 .open = exports_open, 134 .open = exports_open,
135 .read = seq_read, 135 .read = seq_read,
136 .llseek = seq_lseek, 136 .llseek = seq_lseek,
137 .release = seq_release, 137 .release = seq_release,
138 .owner = THIS_MODULE, 138 .owner = THIS_MODULE,
139 }; 139 };
140 140
141 static int export_features_show(struct seq_file *m, void *v) 141 static int export_features_show(struct seq_file *m, void *v)
142 { 142 {
143 seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS); 143 seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
144 return 0; 144 return 0;
145 } 145 }
146 146
147 static int export_features_open(struct inode *inode, struct file *file) 147 static int export_features_open(struct inode *inode, struct file *file)
148 { 148 {
149 return single_open(file, export_features_show, NULL); 149 return single_open(file, export_features_show, NULL);
150 } 150 }
151 151
152 static struct file_operations export_features_operations = { 152 static struct file_operations export_features_operations = {
153 .open = export_features_open, 153 .open = export_features_open,
154 .read = seq_read, 154 .read = seq_read,
155 .llseek = seq_lseek, 155 .llseek = seq_lseek,
156 .release = single_release, 156 .release = single_release,
157 }; 157 };
158 158
159 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) 159 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
160 static int supported_enctypes_show(struct seq_file *m, void *v) 160 static int supported_enctypes_show(struct seq_file *m, void *v)
161 { 161 {
162 seq_printf(m, KRB5_SUPPORTED_ENCTYPES); 162 seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
163 return 0; 163 return 0;
164 } 164 }
165 165
166 static int supported_enctypes_open(struct inode *inode, struct file *file) 166 static int supported_enctypes_open(struct inode *inode, struct file *file)
167 { 167 {
168 return single_open(file, supported_enctypes_show, NULL); 168 return single_open(file, supported_enctypes_show, NULL);
169 } 169 }
170 170
171 static struct file_operations supported_enctypes_ops = { 171 static struct file_operations supported_enctypes_ops = {
172 .open = supported_enctypes_open, 172 .open = supported_enctypes_open,
173 .read = seq_read, 173 .read = seq_read,
174 .llseek = seq_lseek, 174 .llseek = seq_lseek,
175 .release = single_release, 175 .release = single_release,
176 }; 176 };
177 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ 177 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
178 178
179 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); 179 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
180 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); 180 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
181 181
182 static const struct file_operations pool_stats_operations = { 182 static const struct file_operations pool_stats_operations = {
183 .open = nfsd_pool_stats_open, 183 .open = nfsd_pool_stats_open,
184 .read = seq_read, 184 .read = seq_read,
185 .llseek = seq_lseek, 185 .llseek = seq_lseek,
186 .release = nfsd_pool_stats_release, 186 .release = nfsd_pool_stats_release,
187 .owner = THIS_MODULE, 187 .owner = THIS_MODULE,
188 }; 188 };
189 189
190 /*----------------------------------------------------------------------------*/ 190 /*----------------------------------------------------------------------------*/
191 /* 191 /*
192 * payload - write methods 192 * payload - write methods
193 */ 193 */
194 194
195 195
196 /** 196 /**
197 * write_unlock_ip - Release all locks used by a client 197 * write_unlock_ip - Release all locks used by a client
198 * 198 *
199 * Experimental. 199 * Experimental.
200 * 200 *
201 * Input: 201 * Input:
202 * buf: '\n'-terminated C string containing a 202 * buf: '\n'-terminated C string containing a
203 * presentation format IP address 203 * presentation format IP address
204 * size: length of C string in @buf 204 * size: length of C string in @buf
205 * Output: 205 * Output:
206 * On success: returns zero if all specified locks were released; 206 * On success: returns zero if all specified locks were released;
207 * returns one if one or more locks were not released 207 * returns one if one or more locks were not released
208 * On error: return code is negative errno value 208 * On error: return code is negative errno value
209 */ 209 */
210 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) 210 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
211 { 211 {
212 struct sockaddr_storage address; 212 struct sockaddr_storage address;
213 struct sockaddr *sap = (struct sockaddr *)&address; 213 struct sockaddr *sap = (struct sockaddr *)&address;
214 size_t salen = sizeof(address); 214 size_t salen = sizeof(address);
215 char *fo_path; 215 char *fo_path;
216 216
217 /* sanity check */ 217 /* sanity check */
218 if (size == 0) 218 if (size == 0)
219 return -EINVAL; 219 return -EINVAL;
220 220
221 if (buf[size-1] != '\n') 221 if (buf[size-1] != '\n')
222 return -EINVAL; 222 return -EINVAL;
223 223
224 fo_path = buf; 224 fo_path = buf;
225 if (qword_get(&buf, fo_path, size) < 0) 225 if (qword_get(&buf, fo_path, size) < 0)
226 return -EINVAL; 226 return -EINVAL;
227 227
228 if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0) 228 if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0)
229 return -EINVAL; 229 return -EINVAL;
230 230
231 return nlmsvc_unlock_all_by_ip(sap); 231 return nlmsvc_unlock_all_by_ip(sap);
232 } 232 }
233 233
234 /** 234 /**
235 * write_unlock_fs - Release all locks on a local file system 235 * write_unlock_fs - Release all locks on a local file system
236 * 236 *
237 * Experimental. 237 * Experimental.
238 * 238 *
239 * Input: 239 * Input:
240 * buf: '\n'-terminated C string containing the 240 * buf: '\n'-terminated C string containing the
241 * absolute pathname of a local file system 241 * absolute pathname of a local file system
242 * size: length of C string in @buf 242 * size: length of C string in @buf
243 * Output: 243 * Output:
244 * On success: returns zero if all specified locks were released; 244 * On success: returns zero if all specified locks were released;
245 * returns one if one or more locks were not released 245 * returns one if one or more locks were not released
246 * On error: return code is negative errno value 246 * On error: return code is negative errno value
247 */ 247 */
248 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) 248 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
249 { 249 {
250 struct path path; 250 struct path path;
251 char *fo_path; 251 char *fo_path;
252 int error; 252 int error;
253 253
254 /* sanity check */ 254 /* sanity check */
255 if (size == 0) 255 if (size == 0)
256 return -EINVAL; 256 return -EINVAL;
257 257
258 if (buf[size-1] != '\n') 258 if (buf[size-1] != '\n')
259 return -EINVAL; 259 return -EINVAL;
260 260
261 fo_path = buf; 261 fo_path = buf;
262 if (qword_get(&buf, fo_path, size) < 0) 262 if (qword_get(&buf, fo_path, size) < 0)
263 return -EINVAL; 263 return -EINVAL;
264 264
265 error = kern_path(fo_path, 0, &path); 265 error = kern_path(fo_path, 0, &path);
266 if (error) 266 if (error)
267 return error; 267 return error;
268 268
269 /* 269 /*
270 * XXX: Needs better sanity checking. Otherwise we could end up 270 * XXX: Needs better sanity checking. Otherwise we could end up
271 * releasing locks on the wrong file system. 271 * releasing locks on the wrong file system.
272 * 272 *
273 * For example: 273 * For example:
274 * 1. Does the path refer to a directory? 274 * 1. Does the path refer to a directory?
275 * 2. Is that directory a mount point, or 275 * 2. Is that directory a mount point, or
276 * 3. Is that directory the root of an exported file system? 276 * 3. Is that directory the root of an exported file system?
277 */ 277 */
278 error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb); 278 error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
279 279
280 path_put(&path); 280 path_put(&path);
281 return error; 281 return error;
282 } 282 }
283 283
284 /** 284 /**
285 * write_filehandle - Get a variable-length NFS file handle by path 285 * write_filehandle - Get a variable-length NFS file handle by path
286 * 286 *
287 * On input, the buffer contains a '\n'-terminated C string comprised of 287 * On input, the buffer contains a '\n'-terminated C string comprised of
288 * three alphanumeric words separated by whitespace. The string may 288 * three alphanumeric words separated by whitespace. The string may
289 * contain escape sequences. 289 * contain escape sequences.
290 * 290 *
291 * Input: 291 * Input:
292 * buf: 292 * buf:
293 * domain: client domain name 293 * domain: client domain name
294 * path: export pathname 294 * path: export pathname
295 * maxsize: numeric maximum size of 295 * maxsize: numeric maximum size of
296 * @buf 296 * @buf
297 * size: length of C string in @buf 297 * size: length of C string in @buf
298 * Output: 298 * Output:
299 * On success: passed-in buffer filled with '\n'-terminated C 299 * On success: passed-in buffer filled with '\n'-terminated C
300 * string containing a ASCII hex text version 300 * string containing a ASCII hex text version
301 * of the NFS file handle; 301 * of the NFS file handle;
302 * return code is the size in bytes of the string 302 * return code is the size in bytes of the string
303 * On error: return code is negative errno value 303 * On error: return code is negative errno value
304 */ 304 */
305 static ssize_t write_filehandle(struct file *file, char *buf, size_t size) 305 static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
306 { 306 {
307 char *dname, *path; 307 char *dname, *path;
308 int uninitialized_var(maxsize); 308 int uninitialized_var(maxsize);
309 char *mesg = buf; 309 char *mesg = buf;
310 int len; 310 int len;
311 struct auth_domain *dom; 311 struct auth_domain *dom;
312 struct knfsd_fh fh; 312 struct knfsd_fh fh;
313 313
314 if (size == 0) 314 if (size == 0)
315 return -EINVAL; 315 return -EINVAL;
316 316
317 if (buf[size-1] != '\n') 317 if (buf[size-1] != '\n')
318 return -EINVAL; 318 return -EINVAL;
319 buf[size-1] = 0; 319 buf[size-1] = 0;
320 320
321 dname = mesg; 321 dname = mesg;
322 len = qword_get(&mesg, dname, size); 322 len = qword_get(&mesg, dname, size);
323 if (len <= 0) 323 if (len <= 0)
324 return -EINVAL; 324 return -EINVAL;
325 325
326 path = dname+len+1; 326 path = dname+len+1;
327 len = qword_get(&mesg, path, size); 327 len = qword_get(&mesg, path, size);
328 if (len <= 0) 328 if (len <= 0)
329 return -EINVAL; 329 return -EINVAL;
330 330
331 len = get_int(&mesg, &maxsize); 331 len = get_int(&mesg, &maxsize);
332 if (len) 332 if (len)
333 return len; 333 return len;
334 334
335 if (maxsize < NFS_FHSIZE) 335 if (maxsize < NFS_FHSIZE)
336 return -EINVAL; 336 return -EINVAL;
337 if (maxsize > NFS3_FHSIZE) 337 if (maxsize > NFS3_FHSIZE)
338 maxsize = NFS3_FHSIZE; 338 maxsize = NFS3_FHSIZE;
339 339
340 if (qword_get(&mesg, mesg, size)>0) 340 if (qword_get(&mesg, mesg, size)>0)
341 return -EINVAL; 341 return -EINVAL;
342 342
343 /* we have all the words, they are in buf.. */ 343 /* we have all the words, they are in buf.. */
344 dom = unix_domain_find(dname); 344 dom = unix_domain_find(dname);
345 if (!dom) 345 if (!dom)
346 return -ENOMEM; 346 return -ENOMEM;
347 347
348 len = exp_rootfh(dom, path, &fh, maxsize); 348 len = exp_rootfh(dom, path, &fh, maxsize);
349 auth_domain_put(dom); 349 auth_domain_put(dom);
350 if (len) 350 if (len)
351 return len; 351 return len;
352 352
353 mesg = buf; 353 mesg = buf;
354 len = SIMPLE_TRANSACTION_LIMIT; 354 len = SIMPLE_TRANSACTION_LIMIT;
355 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); 355 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
356 mesg[-1] = '\n'; 356 mesg[-1] = '\n';
357 return mesg - buf; 357 return mesg - buf;
358 } 358 }
359 359
360 /** 360 /**
361 * write_threads - Start NFSD, or report the current number of running threads 361 * write_threads - Start NFSD, or report the current number of running threads
362 * 362 *
363 * Input: 363 * Input:
364 * buf: ignored 364 * buf: ignored
365 * size: zero 365 * size: zero
366 * Output: 366 * Output:
367 * On success: passed-in buffer filled with '\n'-terminated C 367 * On success: passed-in buffer filled with '\n'-terminated C
368 * string numeric value representing the number of 368 * string numeric value representing the number of
369 * running NFSD threads; 369 * running NFSD threads;
370 * return code is the size in bytes of the string 370 * return code is the size in bytes of the string
371 * On error: return code is zero 371 * On error: return code is zero
372 * 372 *
373 * OR 373 * OR
374 * 374 *
375 * Input: 375 * Input:
376 * buf: C string containing an unsigned 376 * buf: C string containing an unsigned
377 * integer value representing the 377 * integer value representing the
378 * number of NFSD threads to start 378 * number of NFSD threads to start
379 * size: non-zero length of C string in @buf 379 * size: non-zero length of C string in @buf
380 * Output: 380 * Output:
381 * On success: NFS service is started; 381 * On success: NFS service is started;
382 * passed-in buffer filled with '\n'-terminated C 382 * passed-in buffer filled with '\n'-terminated C
383 * string numeric value representing the number of 383 * string numeric value representing the number of
384 * running NFSD threads; 384 * running NFSD threads;
385 * return code is the size in bytes of the string 385 * return code is the size in bytes of the string
386 * On error: return code is zero or a negative errno value 386 * On error: return code is zero or a negative errno value
387 */ 387 */
388 static ssize_t write_threads(struct file *file, char *buf, size_t size) 388 static ssize_t write_threads(struct file *file, char *buf, size_t size)
389 { 389 {
390 char *mesg = buf; 390 char *mesg = buf;
391 int rv; 391 int rv;
392 if (size > 0) { 392 if (size > 0) {
393 int newthreads; 393 int newthreads;
394 rv = get_int(&mesg, &newthreads); 394 rv = get_int(&mesg, &newthreads);
395 if (rv) 395 if (rv)
396 return rv; 396 return rv;
397 if (newthreads < 0) 397 if (newthreads < 0)
398 return -EINVAL; 398 return -EINVAL;
399 rv = nfsd_svc(NFS_PORT, newthreads); 399 rv = nfsd_svc(NFS_PORT, newthreads);
400 if (rv < 0) 400 if (rv < 0)
401 return rv; 401 return rv;
402 } else 402 } else
403 rv = nfsd_nrthreads(); 403 rv = nfsd_nrthreads();
404 404
405 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv); 405 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
406 } 406 }
407 407
408 /** 408 /**
409 * write_pool_threads - Set or report the current number of threads per pool 409 * write_pool_threads - Set or report the current number of threads per pool
410 * 410 *
411 * Input: 411 * Input:
412 * buf: ignored 412 * buf: ignored
413 * size: zero 413 * size: zero
414 * 414 *
415 * OR 415 * OR
416 * 416 *
417 * Input: 417 * Input:
418 * buf: C string containing whitespace- 418 * buf: C string containing whitespace-
419 * separated unsigned integer values 419 * separated unsigned integer values
420 * representing the number of NFSD 420 * representing the number of NFSD
421 * threads to start in each pool 421 * threads to start in each pool
422 * size: non-zero length of C string in @buf 422 * size: non-zero length of C string in @buf
423 * Output: 423 * Output:
424 * On success: passed-in buffer filled with '\n'-terminated C 424 * On success: passed-in buffer filled with '\n'-terminated C
425 * string containing integer values representing the 425 * string containing integer values representing the
426 * number of NFSD threads in each pool; 426 * number of NFSD threads in each pool;
427 * return code is the size in bytes of the string 427 * return code is the size in bytes of the string
428 * On error: return code is zero or a negative errno value 428 * On error: return code is zero or a negative errno value
429 */ 429 */
430 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) 430 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
431 { 431 {
432 /* if size > 0, look for an array of number of threads per node 432 /* if size > 0, look for an array of number of threads per node
433 * and apply them then write out number of threads per node as reply 433 * and apply them then write out number of threads per node as reply
434 */ 434 */
435 char *mesg = buf; 435 char *mesg = buf;
436 int i; 436 int i;
437 int rv; 437 int rv;
438 int len; 438 int len;
439 int npools; 439 int npools;
440 int *nthreads; 440 int *nthreads;
441 441
442 mutex_lock(&nfsd_mutex); 442 mutex_lock(&nfsd_mutex);
443 npools = nfsd_nrpools(); 443 npools = nfsd_nrpools();
444 if (npools == 0) { 444 if (npools == 0) {
445 /* 445 /*
446 * NFS is shut down. The admin can start it by 446 * NFS is shut down. The admin can start it by
447 * writing to the threads file but NOT the pool_threads 447 * writing to the threads file but NOT the pool_threads
448 * file, sorry. Report zero threads. 448 * file, sorry. Report zero threads.
449 */ 449 */
450 mutex_unlock(&nfsd_mutex); 450 mutex_unlock(&nfsd_mutex);
451 strcpy(buf, "0\n"); 451 strcpy(buf, "0\n");
452 return strlen(buf); 452 return strlen(buf);
453 } 453 }
454 454
455 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); 455 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
456 rv = -ENOMEM; 456 rv = -ENOMEM;
457 if (nthreads == NULL) 457 if (nthreads == NULL)
458 goto out_free; 458 goto out_free;
459 459
460 if (size > 0) { 460 if (size > 0) {
461 for (i = 0; i < npools; i++) { 461 for (i = 0; i < npools; i++) {
462 rv = get_int(&mesg, &nthreads[i]); 462 rv = get_int(&mesg, &nthreads[i]);
463 if (rv == -ENOENT) 463 if (rv == -ENOENT)
464 break; /* fewer numbers than pools */ 464 break; /* fewer numbers than pools */
465 if (rv) 465 if (rv)
466 goto out_free; /* syntax error */ 466 goto out_free; /* syntax error */
467 rv = -EINVAL; 467 rv = -EINVAL;
468 if (nthreads[i] < 0) 468 if (nthreads[i] < 0)
469 goto out_free; 469 goto out_free;
470 } 470 }
471 rv = nfsd_set_nrthreads(i, nthreads); 471 rv = nfsd_set_nrthreads(i, nthreads);
472 if (rv) 472 if (rv)
473 goto out_free; 473 goto out_free;
474 } 474 }
475 475
476 rv = nfsd_get_nrthreads(npools, nthreads); 476 rv = nfsd_get_nrthreads(npools, nthreads);
477 if (rv) 477 if (rv)
478 goto out_free; 478 goto out_free;
479 479
480 mesg = buf; 480 mesg = buf;
481 size = SIMPLE_TRANSACTION_LIMIT; 481 size = SIMPLE_TRANSACTION_LIMIT;
482 for (i = 0; i < npools && size > 0; i++) { 482 for (i = 0; i < npools && size > 0; i++) {
483 snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' ')); 483 snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
484 len = strlen(mesg); 484 len = strlen(mesg);
485 size -= len; 485 size -= len;
486 mesg += len; 486 mesg += len;
487 } 487 }
488 rv = mesg - buf; 488 rv = mesg - buf;
489 out_free: 489 out_free:
490 kfree(nthreads); 490 kfree(nthreads);
491 mutex_unlock(&nfsd_mutex); 491 mutex_unlock(&nfsd_mutex);
492 return rv; 492 return rv;
493 } 493 }
494 494
495 static ssize_t __write_versions(struct file *file, char *buf, size_t size) 495 static ssize_t __write_versions(struct file *file, char *buf, size_t size)
496 { 496 {
497 char *mesg = buf; 497 char *mesg = buf;
498 char *vers, *minorp, sign; 498 char *vers, *minorp, sign;
499 int len, num, remaining; 499 int len, num, remaining;
500 unsigned minor; 500 unsigned minor;
501 ssize_t tlen = 0; 501 ssize_t tlen = 0;
502 char *sep; 502 char *sep;
503 503
504 if (size>0) { 504 if (size>0) {
505 if (nfsd_serv) 505 if (nfsd_serv)
506 /* Cannot change versions without updating 506 /* Cannot change versions without updating
507 * nfsd_serv->sv_xdrsize, and reallocing 507 * nfsd_serv->sv_xdrsize, and reallocing
508 * rq_argp and rq_resp 508 * rq_argp and rq_resp
509 */ 509 */
510 return -EBUSY; 510 return -EBUSY;
511 if (buf[size-1] != '\n') 511 if (buf[size-1] != '\n')
512 return -EINVAL; 512 return -EINVAL;
513 buf[size-1] = 0; 513 buf[size-1] = 0;
514 514
515 vers = mesg; 515 vers = mesg;
516 len = qword_get(&mesg, vers, size); 516 len = qword_get(&mesg, vers, size);
517 if (len <= 0) return -EINVAL; 517 if (len <= 0) return -EINVAL;
518 do { 518 do {
519 sign = *vers; 519 sign = *vers;
520 if (sign == '+' || sign == '-') 520 if (sign == '+' || sign == '-')
521 num = simple_strtol((vers+1), &minorp, 0); 521 num = simple_strtol((vers+1), &minorp, 0);
522 else 522 else
523 num = simple_strtol(vers, &minorp, 0); 523 num = simple_strtol(vers, &minorp, 0);
524 if (*minorp == '.') { 524 if (*minorp == '.') {
525 if (num < 4) 525 if (num < 4)
526 return -EINVAL; 526 return -EINVAL;
527 minor = simple_strtoul(minorp+1, NULL, 0); 527 minor = simple_strtoul(minorp+1, NULL, 0);
528 if (minor == 0) 528 if (minor == 0)
529 return -EINVAL; 529 return -EINVAL;
530 if (nfsd_minorversion(minor, sign == '-' ? 530 if (nfsd_minorversion(minor, sign == '-' ?
531 NFSD_CLEAR : NFSD_SET) < 0) 531 NFSD_CLEAR : NFSD_SET) < 0)
532 return -EINVAL; 532 return -EINVAL;
533 goto next; 533 goto next;
534 } 534 }
535 switch(num) { 535 switch(num) {
536 case 2: 536 case 2:
537 case 3: 537 case 3:
538 case 4: 538 case 4:
539 nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET); 539 nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
540 break; 540 break;
541 default: 541 default:
542 return -EINVAL; 542 return -EINVAL;
543 } 543 }
544 next: 544 next:
545 vers += len + 1; 545 vers += len + 1;
546 } while ((len = qword_get(&mesg, vers, size)) > 0); 546 } while ((len = qword_get(&mesg, vers, size)) > 0);
547 /* If all get turned off, turn them back on, as 547 /* If all get turned off, turn them back on, as
548 * having no versions is BAD 548 * having no versions is BAD
549 */ 549 */
550 nfsd_reset_versions(); 550 nfsd_reset_versions();
551 } 551 }
552 552
553 /* Now write current state into reply buffer */ 553 /* Now write current state into reply buffer */
554 len = 0; 554 len = 0;
555 sep = ""; 555 sep = "";
556 remaining = SIMPLE_TRANSACTION_LIMIT; 556 remaining = SIMPLE_TRANSACTION_LIMIT;
557 for (num=2 ; num <= 4 ; num++) 557 for (num=2 ; num <= 4 ; num++)
558 if (nfsd_vers(num, NFSD_AVAIL)) { 558 if (nfsd_vers(num, NFSD_AVAIL)) {
559 len = snprintf(buf, remaining, "%s%c%d", sep, 559 len = snprintf(buf, remaining, "%s%c%d", sep,
560 nfsd_vers(num, NFSD_TEST)?'+':'-', 560 nfsd_vers(num, NFSD_TEST)?'+':'-',
561 num); 561 num);
562 sep = " "; 562 sep = " ";
563 563
564 if (len > remaining) 564 if (len > remaining)
565 break; 565 break;
566 remaining -= len; 566 remaining -= len;
567 buf += len; 567 buf += len;
568 tlen += len; 568 tlen += len;
569 } 569 }
570 if (nfsd_vers(4, NFSD_AVAIL)) 570 if (nfsd_vers(4, NFSD_AVAIL))
571 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; 571 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
572 minor++) { 572 minor++) {
573 len = snprintf(buf, remaining, " %c4.%u", 573 len = snprintf(buf, remaining, " %c4.%u",
574 (nfsd_vers(4, NFSD_TEST) && 574 (nfsd_vers(4, NFSD_TEST) &&
575 nfsd_minorversion(minor, NFSD_TEST)) ? 575 nfsd_minorversion(minor, NFSD_TEST)) ?
576 '+' : '-', 576 '+' : '-',
577 minor); 577 minor);
578 578
579 if (len > remaining) 579 if (len > remaining)
580 break; 580 break;
581 remaining -= len; 581 remaining -= len;
582 buf += len; 582 buf += len;
583 tlen += len; 583 tlen += len;
584 } 584 }
585 585
586 len = snprintf(buf, remaining, "\n"); 586 len = snprintf(buf, remaining, "\n");
587 if (len > remaining) 587 if (len > remaining)
588 return -EINVAL; 588 return -EINVAL;
589 return tlen + len; 589 return tlen + len;
590 } 590 }
591 591
592 /** 592 /**
593 * write_versions - Set or report the available NFS protocol versions 593 * write_versions - Set or report the available NFS protocol versions
594 * 594 *
595 * Input: 595 * Input:
596 * buf: ignored 596 * buf: ignored
597 * size: zero 597 * size: zero
598 * Output: 598 * Output:
599 * On success: passed-in buffer filled with '\n'-terminated C 599 * On success: passed-in buffer filled with '\n'-terminated C
600 * string containing positive or negative integer 600 * string containing positive or negative integer
601 * values representing the current status of each 601 * values representing the current status of each
602 * protocol version; 602 * protocol version;
603 * return code is the size in bytes of the string 603 * return code is the size in bytes of the string
604 * On error: return code is zero or a negative errno value 604 * On error: return code is zero or a negative errno value
605 * 605 *
606 * OR 606 * OR
607 * 607 *
608 * Input: 608 * Input:
609 * buf: C string containing whitespace- 609 * buf: C string containing whitespace-
610 * separated positive or negative 610 * separated positive or negative
611 * integer values representing NFS 611 * integer values representing NFS
612 * protocol versions to enable ("+n") 612 * protocol versions to enable ("+n")
613 * or disable ("-n") 613 * or disable ("-n")
614 * size: non-zero length of C string in @buf 614 * size: non-zero length of C string in @buf
615 * Output: 615 * Output:
616 * On success: status of zero or more protocol versions has 616 * On success: status of zero or more protocol versions has
617 * been updated; passed-in buffer filled with 617 * been updated; passed-in buffer filled with
618 * '\n'-terminated C string containing positive 618 * '\n'-terminated C string containing positive
619 * or negative integer values representing the 619 * or negative integer values representing the
620 * current status of each protocol version; 620 * current status of each protocol version;
621 * return code is the size in bytes of the string 621 * return code is the size in bytes of the string
622 * On error: return code is zero or a negative errno value 622 * On error: return code is zero or a negative errno value
623 */ 623 */
624 static ssize_t write_versions(struct file *file, char *buf, size_t size) 624 static ssize_t write_versions(struct file *file, char *buf, size_t size)
625 { 625 {
626 ssize_t rv; 626 ssize_t rv;
627 627
628 mutex_lock(&nfsd_mutex); 628 mutex_lock(&nfsd_mutex);
629 rv = __write_versions(file, buf, size); 629 rv = __write_versions(file, buf, size);
630 mutex_unlock(&nfsd_mutex); 630 mutex_unlock(&nfsd_mutex);
631 return rv; 631 return rv;
632 } 632 }
633 633
634 /* 634 /*
635 * Zero-length write. Return a list of NFSD's current listener 635 * Zero-length write. Return a list of NFSD's current listener
636 * transports. 636 * transports.
637 */ 637 */
638 static ssize_t __write_ports_names(char *buf) 638 static ssize_t __write_ports_names(char *buf)
639 { 639 {
640 if (nfsd_serv == NULL) 640 if (nfsd_serv == NULL)
641 return 0; 641 return 0;
642 return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT); 642 return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
643 } 643 }
644 644
645 /* 645 /*
646 * A single 'fd' number was written, in which case it must be for 646 * A single 'fd' number was written, in which case it must be for
647 * a socket of a supported family/protocol, and we use it as an 647 * a socket of a supported family/protocol, and we use it as an
648 * nfsd listener. 648 * nfsd listener.
649 */ 649 */
650 static ssize_t __write_ports_addfd(char *buf) 650 static ssize_t __write_ports_addfd(char *buf)
651 { 651 {
652 char *mesg = buf; 652 char *mesg = buf;
653 int fd, err; 653 int fd, err;
654 654
655 err = get_int(&mesg, &fd); 655 err = get_int(&mesg, &fd);
656 if (err != 0 || fd < 0) 656 if (err != 0 || fd < 0)
657 return -EINVAL; 657 return -EINVAL;
658 658
659 err = nfsd_create_serv(); 659 err = nfsd_create_serv();
660 if (err != 0) 660 if (err != 0)
661 return err; 661 return err;
662 662
663 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 663 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
664 if (err < 0) { 664 if (err < 0) {
665 svc_destroy(nfsd_serv); 665 svc_destroy(nfsd_serv);
666 return err; 666 return err;
667 } 667 }
668 668
669 /* Decrease the count, but don't shut down the service */ 669 /* Decrease the count, but don't shut down the service */
670 nfsd_serv->sv_nrthreads--; 670 nfsd_serv->sv_nrthreads--;
671 return err; 671 return err;
672 } 672 }
673 673
674 /* 674 /*
675 * A '-' followed by the 'name' of a socket means we close the socket. 675 * A '-' followed by the 'name' of a socket means we close the socket.
676 */ 676 */
677 static ssize_t __write_ports_delfd(char *buf) 677 static ssize_t __write_ports_delfd(char *buf)
678 { 678 {
679 char *toclose; 679 char *toclose;
680 int len = 0; 680 int len = 0;
681 681
682 toclose = kstrdup(buf + 1, GFP_KERNEL); 682 toclose = kstrdup(buf + 1, GFP_KERNEL);
683 if (toclose == NULL) 683 if (toclose == NULL)
684 return -ENOMEM; 684 return -ENOMEM;
685 685
686 if (nfsd_serv != NULL) 686 if (nfsd_serv != NULL)
687 len = svc_sock_names(nfsd_serv, buf, 687 len = svc_sock_names(nfsd_serv, buf,
688 SIMPLE_TRANSACTION_LIMIT, toclose); 688 SIMPLE_TRANSACTION_LIMIT, toclose);
689 kfree(toclose); 689 kfree(toclose);
690 return len; 690 return len;
691 } 691 }
692 692
693 /* 693 /*
694 * A transport listener is added by writing it's transport name and 694 * A transport listener is added by writing it's transport name and
695 * a port number. 695 * a port number.
696 */ 696 */
697 static ssize_t __write_ports_addxprt(char *buf) 697 static ssize_t __write_ports_addxprt(char *buf)
698 { 698 {
699 char transport[16]; 699 char transport[16];
700 struct svc_xprt *xprt; 700 struct svc_xprt *xprt;
701 int port, err; 701 int port, err;
702 702
703 if (sscanf(buf, "%15s %4u", transport, &port) != 2) 703 if (sscanf(buf, "%15s %4u", transport, &port) != 2)
704 return -EINVAL; 704 return -EINVAL;
705 705
706 if (port < 1 || port > USHRT_MAX) 706 if (port < 1 || port > USHRT_MAX)
707 return -EINVAL; 707 return -EINVAL;
708 708
709 err = nfsd_create_serv(); 709 err = nfsd_create_serv();
710 if (err != 0) 710 if (err != 0)
711 return err; 711 return err;
712 712
713 err = svc_create_xprt(nfsd_serv, transport, &init_net, 713 err = svc_create_xprt(nfsd_serv, transport, &init_net,
714 PF_INET, port, SVC_SOCK_ANONYMOUS); 714 PF_INET, port, SVC_SOCK_ANONYMOUS);
715 if (err < 0) 715 if (err < 0)
716 goto out_err; 716 goto out_err;
717 717
718 err = svc_create_xprt(nfsd_serv, transport, &init_net, 718 err = svc_create_xprt(nfsd_serv, transport, &init_net,
719 PF_INET6, port, SVC_SOCK_ANONYMOUS); 719 PF_INET6, port, SVC_SOCK_ANONYMOUS);
720 if (err < 0 && err != -EAFNOSUPPORT) 720 if (err < 0 && err != -EAFNOSUPPORT)
721 goto out_close; 721 goto out_close;
722 722
723 /* Decrease the count, but don't shut down the service */ 723 /* Decrease the count, but don't shut down the service */
724 nfsd_serv->sv_nrthreads--; 724 nfsd_serv->sv_nrthreads--;
725 return 0; 725 return 0;
726 out_close: 726 out_close:
727 xprt = svc_find_xprt(nfsd_serv, transport, &init_net, PF_INET, port); 727 xprt = svc_find_xprt(nfsd_serv, transport, &init_net, PF_INET, port);
728 if (xprt != NULL) { 728 if (xprt != NULL) {
729 svc_close_xprt(xprt); 729 svc_close_xprt(xprt);
730 svc_xprt_put(xprt); 730 svc_xprt_put(xprt);
731 } 731 }
732 out_err: 732 out_err:
733 svc_destroy(nfsd_serv); 733 svc_destroy(nfsd_serv);
734 return err; 734 return err;
735 } 735 }
736 736
737 /* 737 /*
738 * A transport listener is removed by writing a "-", it's transport 738 * A transport listener is removed by writing a "-", it's transport
739 * name, and it's port number. 739 * name, and it's port number.
740 */ 740 */
741 static ssize_t __write_ports_delxprt(char *buf) 741 static ssize_t __write_ports_delxprt(char *buf)
742 { 742 {
743 struct svc_xprt *xprt; 743 struct svc_xprt *xprt;
744 char transport[16]; 744 char transport[16];
745 int port; 745 int port;
746 746
747 if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2) 747 if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
748 return -EINVAL; 748 return -EINVAL;
749 749
750 if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL) 750 if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
751 return -EINVAL; 751 return -EINVAL;
752 752
753 xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port); 753 xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port);
754 if (xprt == NULL) 754 if (xprt == NULL)
755 return -ENOTCONN; 755 return -ENOTCONN;
756 756
757 svc_close_xprt(xprt); 757 svc_close_xprt(xprt);
758 svc_xprt_put(xprt); 758 svc_xprt_put(xprt);
759 return 0; 759 return 0;
760 } 760 }
761 761
762 static ssize_t __write_ports(struct file *file, char *buf, size_t size) 762 static ssize_t __write_ports(struct file *file, char *buf, size_t size)
763 { 763 {
764 if (size == 0) 764 if (size == 0)
765 return __write_ports_names(buf); 765 return __write_ports_names(buf);
766 766
767 if (isdigit(buf[0])) 767 if (isdigit(buf[0]))
768 return __write_ports_addfd(buf); 768 return __write_ports_addfd(buf);
769 769
770 if (buf[0] == '-' && isdigit(buf[1])) 770 if (buf[0] == '-' && isdigit(buf[1]))
771 return __write_ports_delfd(buf); 771 return __write_ports_delfd(buf);
772 772
773 if (isalpha(buf[0])) 773 if (isalpha(buf[0]))
774 return __write_ports_addxprt(buf); 774 return __write_ports_addxprt(buf);
775 775
776 if (buf[0] == '-' && isalpha(buf[1])) 776 if (buf[0] == '-' && isalpha(buf[1]))
777 return __write_ports_delxprt(buf); 777 return __write_ports_delxprt(buf);
778 778
779 return -EINVAL; 779 return -EINVAL;
780 } 780 }
781 781
782 /** 782 /**
783 * write_ports - Pass a socket file descriptor or transport name to listen on 783 * write_ports - Pass a socket file descriptor or transport name to listen on
784 * 784 *
785 * Input: 785 * Input:
786 * buf: ignored 786 * buf: ignored
787 * size: zero 787 * size: zero
788 * Output: 788 * Output:
789 * On success: passed-in buffer filled with a '\n'-terminated C 789 * On success: passed-in buffer filled with a '\n'-terminated C
790 * string containing a whitespace-separated list of 790 * string containing a whitespace-separated list of
791 * named NFSD listeners; 791 * named NFSD listeners;
792 * return code is the size in bytes of the string 792 * return code is the size in bytes of the string
793 * On error: return code is zero or a negative errno value 793 * On error: return code is zero or a negative errno value
794 * 794 *
795 * OR 795 * OR
796 * 796 *
797 * Input: 797 * Input:
798 * buf: C string containing an unsigned 798 * buf: C string containing an unsigned
799 * integer value representing a bound 799 * integer value representing a bound
800 * but unconnected socket that is to be 800 * but unconnected socket that is to be
801 * used as an NFSD listener; listen(3) 801 * used as an NFSD listener; listen(3)
802 * must be called for a SOCK_STREAM 802 * must be called for a SOCK_STREAM
803 * socket, otherwise it is ignored 803 * socket, otherwise it is ignored
804 * size: non-zero length of C string in @buf 804 * size: non-zero length of C string in @buf
805 * Output: 805 * Output:
806 * On success: NFS service is started; 806 * On success: NFS service is started;
807 * passed-in buffer filled with a '\n'-terminated C 807 * passed-in buffer filled with a '\n'-terminated C
808 * string containing a unique alphanumeric name of 808 * string containing a unique alphanumeric name of
809 * the listener; 809 * the listener;
810 * return code is the size in bytes of the string 810 * return code is the size in bytes of the string
811 * On error: return code is a negative errno value 811 * On error: return code is a negative errno value
812 * 812 *
813 * OR 813 * OR
814 * 814 *
815 * Input: 815 * Input:
816 * buf: C string containing a "-" followed 816 * buf: C string containing a "-" followed
817 * by an integer value representing a 817 * by an integer value representing a
818 * previously passed in socket file 818 * previously passed in socket file
819 * descriptor 819 * descriptor
820 * size: non-zero length of C string in @buf 820 * size: non-zero length of C string in @buf
821 * Output: 821 * Output:
822 * On success: NFS service no longer listens on that socket; 822 * On success: NFS service no longer listens on that socket;
823 * passed-in buffer filled with a '\n'-terminated C 823 * passed-in buffer filled with a '\n'-terminated C
824 * string containing a unique name of the listener; 824 * string containing a unique name of the listener;
825 * return code is the size in bytes of the string 825 * return code is the size in bytes of the string
826 * On error: return code is a negative errno value 826 * On error: return code is a negative errno value
827 * 827 *
828 * OR 828 * OR
829 * 829 *
830 * Input: 830 * Input:
831 * buf: C string containing a transport 831 * buf: C string containing a transport
832 * name and an unsigned integer value 832 * name and an unsigned integer value
833 * representing the port to listen on, 833 * representing the port to listen on,
834 * separated by whitespace 834 * separated by whitespace
835 * size: non-zero length of C string in @buf 835 * size: non-zero length of C string in @buf
836 * Output: 836 * Output:
837 * On success: returns zero; NFS service is started 837 * On success: returns zero; NFS service is started
838 * On error: return code is a negative errno value 838 * On error: return code is a negative errno value
839 * 839 *
840 * OR 840 * OR
841 * 841 *
842 * Input: 842 * Input:
843 * buf: C string containing a "-" followed 843 * buf: C string containing a "-" followed
844 * by a transport name and an unsigned 844 * by a transport name and an unsigned
845 * integer value representing the port 845 * integer value representing the port
846 * to listen on, separated by whitespace 846 * to listen on, separated by whitespace
847 * size: non-zero length of C string in @buf 847 * size: non-zero length of C string in @buf
848 * Output: 848 * Output:
849 * On success: returns zero; NFS service no longer listens 849 * On success: returns zero; NFS service no longer listens
850 * on that transport 850 * on that transport
851 * On error: return code is a negative errno value 851 * On error: return code is a negative errno value
852 */ 852 */
853 static ssize_t write_ports(struct file *file, char *buf, size_t size) 853 static ssize_t write_ports(struct file *file, char *buf, size_t size)
854 { 854 {
855 ssize_t rv; 855 ssize_t rv;
856 856
857 mutex_lock(&nfsd_mutex); 857 mutex_lock(&nfsd_mutex);
858 rv = __write_ports(file, buf, size); 858 rv = __write_ports(file, buf, size);
859 mutex_unlock(&nfsd_mutex); 859 mutex_unlock(&nfsd_mutex);
860 return rv; 860 return rv;
861 } 861 }
862 862
863 863
864 int nfsd_max_blksize; 864 int nfsd_max_blksize;
865 865
866 /** 866 /**
867 * write_maxblksize - Set or report the current NFS blksize 867 * write_maxblksize - Set or report the current NFS blksize
868 * 868 *
869 * Input: 869 * Input:
870 * buf: ignored 870 * buf: ignored
871 * size: zero 871 * size: zero
872 * 872 *
873 * OR 873 * OR
874 * 874 *
875 * Input: 875 * Input:
876 * buf: C string containing an unsigned 876 * buf: C string containing an unsigned
877 * integer value representing the new 877 * integer value representing the new
878 * NFS blksize 878 * NFS blksize
879 * size: non-zero length of C string in @buf 879 * size: non-zero length of C string in @buf
880 * Output: 880 * Output:
881 * On success: passed-in buffer filled with '\n'-terminated C string 881 * On success: passed-in buffer filled with '\n'-terminated C string
882 * containing numeric value of the current NFS blksize 882 * containing numeric value of the current NFS blksize
883 * setting; 883 * setting;
884 * return code is the size in bytes of the string 884 * return code is the size in bytes of the string
885 * On error: return code is zero or a negative errno value 885 * On error: return code is zero or a negative errno value
886 */ 886 */
887 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 887 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
888 { 888 {
889 char *mesg = buf; 889 char *mesg = buf;
890 if (size > 0) { 890 if (size > 0) {
891 int bsize; 891 int bsize;
892 int rv = get_int(&mesg, &bsize); 892 int rv = get_int(&mesg, &bsize);
893 if (rv) 893 if (rv)
894 return rv; 894 return rv;
895 /* force bsize into allowed range and 895 /* force bsize into allowed range and
896 * required alignment. 896 * required alignment.
897 */ 897 */
898 if (bsize < 1024) 898 if (bsize < 1024)
899 bsize = 1024; 899 bsize = 1024;
900 if (bsize > NFSSVC_MAXBLKSIZE) 900 if (bsize > NFSSVC_MAXBLKSIZE)
901 bsize = NFSSVC_MAXBLKSIZE; 901 bsize = NFSSVC_MAXBLKSIZE;
902 bsize &= ~(1024-1); 902 bsize &= ~(1024-1);
903 mutex_lock(&nfsd_mutex); 903 mutex_lock(&nfsd_mutex);
904 if (nfsd_serv) { 904 if (nfsd_serv) {
905 mutex_unlock(&nfsd_mutex); 905 mutex_unlock(&nfsd_mutex);
906 return -EBUSY; 906 return -EBUSY;
907 } 907 }
908 nfsd_max_blksize = bsize; 908 nfsd_max_blksize = bsize;
909 mutex_unlock(&nfsd_mutex); 909 mutex_unlock(&nfsd_mutex);
910 } 910 }
911 911
912 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", 912 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
913 nfsd_max_blksize); 913 nfsd_max_blksize);
914 } 914 }
915 915
916 #ifdef CONFIG_NFSD_V4 916 #ifdef CONFIG_NFSD_V4
917 static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time) 917 static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
918 { 918 {
919 char *mesg = buf; 919 char *mesg = buf;
920 int rv, i; 920 int rv, i;
921 921
922 if (size > 0) { 922 if (size > 0) {
923 if (nfsd_serv) 923 if (nfsd_serv)
924 return -EBUSY; 924 return -EBUSY;
925 rv = get_int(&mesg, &i); 925 rv = get_int(&mesg, &i);
926 if (rv) 926 if (rv)
927 return rv; 927 return rv;
928 /* 928 /*
929 * Some sanity checking. We don't have a reason for 929 * Some sanity checking. We don't have a reason for
930 * these particular numbers, but problems with the 930 * these particular numbers, but problems with the
931 * extremes are: 931 * extremes are:
932 * - Too short: the briefest network outage may 932 * - Too short: the briefest network outage may
933 * cause clients to lose all their locks. Also, 933 * cause clients to lose all their locks. Also,
934 * the frequent polling may be wasteful. 934 * the frequent polling may be wasteful.
935 * - Too long: do you really want reboot recovery 935 * - Too long: do you really want reboot recovery
936 * to take more than an hour? Or to make other 936 * to take more than an hour? Or to make other
937 * clients wait an hour before being able to 937 * clients wait an hour before being able to
938 * revoke a dead client's locks? 938 * revoke a dead client's locks?
939 */ 939 */
940 if (i < 10 || i > 3600) 940 if (i < 10 || i > 3600)
941 return -EINVAL; 941 return -EINVAL;
942 *time = i; 942 *time = i;
943 } 943 }
944 944
945 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time); 945 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
946 } 946 }
947 947
948 static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time) 948 static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
949 { 949 {
950 ssize_t rv; 950 ssize_t rv;
951 951
952 mutex_lock(&nfsd_mutex); 952 mutex_lock(&nfsd_mutex);
953 rv = __nfsd4_write_time(file, buf, size, time); 953 rv = __nfsd4_write_time(file, buf, size, time);
954 mutex_unlock(&nfsd_mutex); 954 mutex_unlock(&nfsd_mutex);
955 return rv; 955 return rv;
956 } 956 }
957 957
958 /** 958 /**
959 * write_leasetime - Set or report the current NFSv4 lease time 959 * write_leasetime - Set or report the current NFSv4 lease time
960 * 960 *
961 * Input: 961 * Input:
962 * buf: ignored 962 * buf: ignored
963 * size: zero 963 * size: zero
964 * 964 *
965 * OR 965 * OR
966 * 966 *
967 * Input: 967 * Input:
968 * buf: C string containing an unsigned 968 * buf: C string containing an unsigned
969 * integer value representing the new 969 * integer value representing the new
970 * NFSv4 lease expiry time 970 * NFSv4 lease expiry time
971 * size: non-zero length of C string in @buf 971 * size: non-zero length of C string in @buf
972 * Output: 972 * Output:
973 * On success: passed-in buffer filled with '\n'-terminated C 973 * On success: passed-in buffer filled with '\n'-terminated C
974 * string containing unsigned integer value of the 974 * string containing unsigned integer value of the
975 * current lease expiry time; 975 * current lease expiry time;
976 * return code is the size in bytes of the string 976 * return code is the size in bytes of the string
977 * On error: return code is zero or a negative errno value 977 * On error: return code is zero or a negative errno value
978 */ 978 */
979 static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 979 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
980 { 980 {
981 return nfsd4_write_time(file, buf, size, &nfsd4_lease); 981 return nfsd4_write_time(file, buf, size, &nfsd4_lease);
982 } 982 }
983 983
984 /** 984 /**
985 * write_gracetime - Set or report current NFSv4 grace period time 985 * write_gracetime - Set or report current NFSv4 grace period time
986 * 986 *
987 * As above, but sets the time of the NFSv4 grace period. 987 * As above, but sets the time of the NFSv4 grace period.
988 * 988 *
989 * Note this should never be set to less than the *previous* 989 * Note this should never be set to less than the *previous*
990 * lease-period time, but we don't try to enforce this. (In the common 990 * lease-period time, but we don't try to enforce this. (In the common
991 * case (a new boot), we don't know what the previous lease time was 991 * case (a new boot), we don't know what the previous lease time was
992 * anyway.) 992 * anyway.)
993 */ 993 */
994 static ssize_t write_gracetime(struct file *file, char *buf, size_t size) 994 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
995 { 995 {
996 return nfsd4_write_time(file, buf, size, &nfsd4_grace); 996 return nfsd4_write_time(file, buf, size, &nfsd4_grace);
997 } 997 }
998 998
999 extern char *nfs4_recoverydir(void); 999 extern char *nfs4_recoverydir(void);
1000 1000
1001 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) 1001 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
1002 { 1002 {
1003 char *mesg = buf; 1003 char *mesg = buf;
1004 char *recdir; 1004 char *recdir;
1005 int len, status; 1005 int len, status;
1006 1006
1007 if (size > 0) { 1007 if (size > 0) {
1008 if (nfsd_serv) 1008 if (nfsd_serv)
1009 return -EBUSY; 1009 return -EBUSY;
1010 if (size > PATH_MAX || buf[size-1] != '\n') 1010 if (size > PATH_MAX || buf[size-1] != '\n')
1011 return -EINVAL; 1011 return -EINVAL;
1012 buf[size-1] = 0; 1012 buf[size-1] = 0;
1013 1013
1014 recdir = mesg; 1014 recdir = mesg;
1015 len = qword_get(&mesg, recdir, size); 1015 len = qword_get(&mesg, recdir, size);
1016 if (len <= 0) 1016 if (len <= 0)
1017 return -EINVAL; 1017 return -EINVAL;
1018 1018
1019 status = nfs4_reset_recoverydir(recdir); 1019 status = nfs4_reset_recoverydir(recdir);
1020 if (status) 1020 if (status)
1021 return status; 1021 return status;
1022 } 1022 }
1023 1023
1024 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n", 1024 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
1025 nfs4_recoverydir()); 1025 nfs4_recoverydir());
1026 } 1026 }
1027 1027
1028 /** 1028 /**
1029 * write_recoverydir - Set or report the pathname of the recovery directory 1029 * write_recoverydir - Set or report the pathname of the recovery directory
1030 * 1030 *
1031 * Input: 1031 * Input:
1032 * buf: ignored 1032 * buf: ignored
1033 * size: zero 1033 * size: zero
1034 * 1034 *
1035 * OR 1035 * OR
1036 * 1036 *
1037 * Input: 1037 * Input:
1038 * buf: C string containing the pathname 1038 * buf: C string containing the pathname
1039 * of the directory on a local file 1039 * of the directory on a local file
1040 * system containing permanent NFSv4 1040 * system containing permanent NFSv4
1041 * recovery data 1041 * recovery data
1042 * size: non-zero length of C string in @buf 1042 * size: non-zero length of C string in @buf
1043 * Output: 1043 * Output:
1044 * On success: passed-in buffer filled with '\n'-terminated C string 1044 * On success: passed-in buffer filled with '\n'-terminated C string
1045 * containing the current recovery pathname setting; 1045 * containing the current recovery pathname setting;
1046 * return code is the size in bytes of the string 1046 * return code is the size in bytes of the string
1047 * On error: return code is zero or a negative errno value 1047 * On error: return code is zero or a negative errno value
1048 */ 1048 */
1049 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 1049 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1050 { 1050 {
1051 ssize_t rv; 1051 ssize_t rv;
1052 1052
1053 mutex_lock(&nfsd_mutex); 1053 mutex_lock(&nfsd_mutex);
1054 rv = __write_recoverydir(file, buf, size); 1054 rv = __write_recoverydir(file, buf, size);
1055 mutex_unlock(&nfsd_mutex); 1055 mutex_unlock(&nfsd_mutex);
1056 return rv; 1056 return rv;
1057 } 1057 }
1058 1058
1059 #endif 1059 #endif
1060 1060
1061 /*----------------------------------------------------------------------------*/ 1061 /*----------------------------------------------------------------------------*/
1062 /* 1062 /*
1063 * populating the filesystem. 1063 * populating the filesystem.
1064 */ 1064 */
1065 1065
1066 static int nfsd_fill_super(struct super_block * sb, void * data, int silent) 1066 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1067 { 1067 {
1068 static struct tree_descr nfsd_files[] = { 1068 static struct tree_descr nfsd_files[] = {
1069 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 1069 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
1070 [NFSD_Export_features] = {"export_features", 1070 [NFSD_Export_features] = {"export_features",
1071 &export_features_operations, S_IRUGO}, 1071 &export_features_operations, S_IRUGO},
1072 [NFSD_FO_UnlockIP] = {"unlock_ip", 1072 [NFSD_FO_UnlockIP] = {"unlock_ip",
1073 &transaction_ops, S_IWUSR|S_IRUSR}, 1073 &transaction_ops, S_IWUSR|S_IRUSR},
1074 [NFSD_FO_UnlockFS] = {"unlock_filesystem", 1074 [NFSD_FO_UnlockFS] = {"unlock_filesystem",
1075 &transaction_ops, S_IWUSR|S_IRUSR}, 1075 &transaction_ops, S_IWUSR|S_IRUSR},
1076 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, 1076 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
1077 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 1077 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
1078 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, 1078 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
1079 [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO}, 1079 [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
1080 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 1080 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1081 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 1081 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1082 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, 1082 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1083 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) 1083 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1084 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, 1084 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1085 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ 1085 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
1086 #ifdef CONFIG_NFSD_V4 1086 #ifdef CONFIG_NFSD_V4
1087 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1087 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1088 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1088 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
1089 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, 1089 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
1090 #endif 1090 #endif
1091 /* last one */ {""} 1091 /* last one */ {""}
1092 }; 1092 };
1093 return simple_fill_super(sb, 0x6e667364, nfsd_files); 1093 return simple_fill_super(sb, 0x6e667364, nfsd_files);
1094 } 1094 }
1095 1095
1096 static struct dentry *nfsd_mount(struct file_system_type *fs_type, 1096 static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1097 int flags, const char *dev_name, void *data) 1097 int flags, const char *dev_name, void *data)
1098 { 1098 {
1099 return mount_single(fs_type, flags, data, nfsd_fill_super); 1099 return mount_single(fs_type, flags, data, nfsd_fill_super);
1100 } 1100 }
1101 1101
1102 static struct file_system_type nfsd_fs_type = { 1102 static struct file_system_type nfsd_fs_type = {
1103 .owner = THIS_MODULE, 1103 .owner = THIS_MODULE,
1104 .name = "nfsd", 1104 .name = "nfsd",
1105 .mount = nfsd_mount, 1105 .mount = nfsd_mount,
1106 .kill_sb = kill_litter_super, 1106 .kill_sb = kill_litter_super,
1107 }; 1107 };
1108 1108
1109 #ifdef CONFIG_PROC_FS 1109 #ifdef CONFIG_PROC_FS
1110 static int create_proc_exports_entry(void) 1110 static int create_proc_exports_entry(void)
1111 { 1111 {
1112 struct proc_dir_entry *entry; 1112 struct proc_dir_entry *entry;
1113 1113
1114 entry = proc_mkdir("fs/nfs", NULL); 1114 entry = proc_mkdir("fs/nfs", NULL);
1115 if (!entry) 1115 if (!entry)
1116 return -ENOMEM; 1116 return -ENOMEM;
1117 entry = proc_create("exports", 0, entry, &exports_operations); 1117 entry = proc_create("exports", 0, entry, &exports_operations);
1118 if (!entry) 1118 if (!entry)
1119 return -ENOMEM; 1119 return -ENOMEM;
1120 return 0; 1120 return 0;
1121 } 1121 }
1122 #else /* CONFIG_PROC_FS */ 1122 #else /* CONFIG_PROC_FS */
1123 static int create_proc_exports_entry(void) 1123 static int create_proc_exports_entry(void)
1124 { 1124 {
1125 return 0; 1125 return 0;
1126 } 1126 }
1127 #endif 1127 #endif
1128 1128
1129 int nfsd_net_id; 1129 int nfsd_net_id;
1130 static struct pernet_operations nfsd_net_ops = { 1130 static struct pernet_operations nfsd_net_ops = {
1131 .id = &nfsd_net_id, 1131 .id = &nfsd_net_id,
1132 .size = sizeof(struct nfsd_net), 1132 .size = sizeof(struct nfsd_net),
1133 }; 1133 };
1134 1134
1135 static int __init init_nfsd(void) 1135 static int __init init_nfsd(void)
1136 { 1136 {
1137 int retval; 1137 int retval;
1138 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); 1138 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
1139 1139
1140 retval = rpc_pipefs_notifier_register(&nfsd4_cld_block); 1140 retval = register_cld_notifier();
1141 if (retval) 1141 if (retval)
1142 return retval; 1142 return retval;
1143 retval = register_pernet_subsys(&nfsd_net_ops); 1143 retval = register_pernet_subsys(&nfsd_net_ops);
1144 if (retval < 0) 1144 if (retval < 0)
1145 goto out_unregister_notifier; 1145 goto out_unregister_notifier;
1146 retval = nfsd4_init_slabs(); 1146 retval = nfsd4_init_slabs();
1147 if (retval) 1147 if (retval)
1148 goto out_unregister_pernet; 1148 goto out_unregister_pernet;
1149 nfs4_state_init(); 1149 nfs4_state_init();
1150 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */ 1150 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */
1151 if (retval) 1151 if (retval)
1152 goto out_free_slabs; 1152 goto out_free_slabs;
1153 nfsd_stat_init(); /* Statistics */ 1153 nfsd_stat_init(); /* Statistics */
1154 retval = nfsd_reply_cache_init(); 1154 retval = nfsd_reply_cache_init();
1155 if (retval) 1155 if (retval)
1156 goto out_free_stat; 1156 goto out_free_stat;
1157 retval = nfsd_export_init(); 1157 retval = nfsd_export_init();
1158 if (retval) 1158 if (retval)
1159 goto out_free_cache; 1159 goto out_free_cache;
1160 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 1160 nfsd_lockd_init(); /* lockd->nfsd callbacks */
1161 retval = nfsd_idmap_init(); 1161 retval = nfsd_idmap_init();
1162 if (retval) 1162 if (retval)
1163 goto out_free_lockd; 1163 goto out_free_lockd;
1164 retval = create_proc_exports_entry(); 1164 retval = create_proc_exports_entry();
1165 if (retval) 1165 if (retval)
1166 goto out_free_idmap; 1166 goto out_free_idmap;
1167 retval = register_filesystem(&nfsd_fs_type); 1167 retval = register_filesystem(&nfsd_fs_type);
1168 if (retval) 1168 if (retval)
1169 goto out_free_all; 1169 goto out_free_all;
1170 return 0; 1170 return 0;
1171 out_free_all: 1171 out_free_all:
1172 remove_proc_entry("fs/nfs/exports", NULL); 1172 remove_proc_entry("fs/nfs/exports", NULL);
1173 remove_proc_entry("fs/nfs", NULL); 1173 remove_proc_entry("fs/nfs", NULL);
1174 out_free_idmap: 1174 out_free_idmap:
1175 nfsd_idmap_shutdown(); 1175 nfsd_idmap_shutdown();
1176 out_free_lockd: 1176 out_free_lockd:
1177 nfsd_lockd_shutdown(); 1177 nfsd_lockd_shutdown();
1178 nfsd_export_shutdown(); 1178 nfsd_export_shutdown();
1179 out_free_cache: 1179 out_free_cache:
1180 nfsd_reply_cache_shutdown(); 1180 nfsd_reply_cache_shutdown();
1181 out_free_stat: 1181 out_free_stat:
1182 nfsd_stat_shutdown(); 1182 nfsd_stat_shutdown();
1183 nfsd_fault_inject_cleanup(); 1183 nfsd_fault_inject_cleanup();
1184 out_free_slabs: 1184 out_free_slabs:
1185 nfsd4_free_slabs(); 1185 nfsd4_free_slabs();
1186 out_unregister_pernet: 1186 out_unregister_pernet:
1187 unregister_pernet_subsys(&nfsd_net_ops); 1187 unregister_pernet_subsys(&nfsd_net_ops);
1188 out_unregister_notifier: 1188 out_unregister_notifier:
1189 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 1189 unregister_cld_notifier();
1190 return retval; 1190 return retval;
1191 } 1191 }
1192 1192
1193 static void __exit exit_nfsd(void) 1193 static void __exit exit_nfsd(void)
1194 { 1194 {
1195 nfsd_export_shutdown(); 1195 nfsd_export_shutdown();
1196 nfsd_reply_cache_shutdown(); 1196 nfsd_reply_cache_shutdown();
1197 remove_proc_entry("fs/nfs/exports", NULL); 1197 remove_proc_entry("fs/nfs/exports", NULL);
1198 remove_proc_entry("fs/nfs", NULL); 1198 remove_proc_entry("fs/nfs", NULL);
1199 nfsd_stat_shutdown(); 1199 nfsd_stat_shutdown();
1200 nfsd_lockd_shutdown(); 1200 nfsd_lockd_shutdown();
1201 nfsd_idmap_shutdown(); 1201 nfsd_idmap_shutdown();
1202 nfsd4_free_slabs(); 1202 nfsd4_free_slabs();
1203 nfsd_fault_inject_cleanup(); 1203 nfsd_fault_inject_cleanup();
1204 unregister_filesystem(&nfsd_fs_type); 1204 unregister_filesystem(&nfsd_fs_type);
1205 unregister_pernet_subsys(&nfsd_net_ops); 1205 unregister_pernet_subsys(&nfsd_net_ops);
1206 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 1206 unregister_cld_notifier();
1207 } 1207 }
1208 1208
1209 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); 1209 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
1210 MODULE_LICENSE("GPL"); 1210 MODULE_LICENSE("GPL");
1211 module_init(init_nfsd) 1211 module_init(init_nfsd)
1212 module_exit(exit_nfsd) 1212 module_exit(exit_nfsd)
1213 1213
1 /* 1 /*
2 * Hodge-podge collection of knfsd-related stuff. 2 * Hodge-podge collection of knfsd-related stuff.
3 * I will sort this out later. 3 * I will sort this out later.
4 * 4 *
5 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 5 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
6 */ 6 */
7 7
8 #ifndef LINUX_NFSD_NFSD_H 8 #ifndef LINUX_NFSD_NFSD_H
9 #define LINUX_NFSD_NFSD_H 9 #define LINUX_NFSD_NFSD_H
10 10
11 #include <linux/types.h> 11 #include <linux/types.h>
12 #include <linux/mount.h> 12 #include <linux/mount.h>
13 13
14 #include <linux/nfs.h> 14 #include <linux/nfs.h>
15 #include <linux/nfs2.h> 15 #include <linux/nfs2.h>
16 #include <linux/nfs3.h> 16 #include <linux/nfs3.h>
17 #include <linux/nfs4.h> 17 #include <linux/nfs4.h>
18 #include <linux/sunrpc/msg_prot.h> 18 #include <linux/sunrpc/msg_prot.h>
19 19
20 #include <linux/nfsd/debug.h> 20 #include <linux/nfsd/debug.h>
21 #include <linux/nfsd/export.h> 21 #include <linux/nfsd/export.h>
22 #include <linux/nfsd/stats.h> 22 #include <linux/nfsd/stats.h>
23 23
24 /* 24 /*
25 * nfsd version 25 * nfsd version
26 */ 26 */
27 #define NFSD_SUPPORTED_MINOR_VERSION 1 27 #define NFSD_SUPPORTED_MINOR_VERSION 1
28 /* 28 /*
29 * Maximum blocksizes supported by daemon under various circumstances. 29 * Maximum blocksizes supported by daemon under various circumstances.
30 */ 30 */
31 #define NFSSVC_MAXBLKSIZE RPCSVC_MAXPAYLOAD 31 #define NFSSVC_MAXBLKSIZE RPCSVC_MAXPAYLOAD
32 /* NFSv2 is limited by the protocol specification, see RFC 1094 */ 32 /* NFSv2 is limited by the protocol specification, see RFC 1094 */
33 #define NFSSVC_MAXBLKSIZE_V2 (8*1024) 33 #define NFSSVC_MAXBLKSIZE_V2 (8*1024)
34 34
35 35
36 /* 36 /*
37 * Largest number of bytes we need to allocate for an NFS 37 * Largest number of bytes we need to allocate for an NFS
38 * call or reply. Used to control buffer sizes. We use 38 * call or reply. Used to control buffer sizes. We use
39 * the length of v3 WRITE, READDIR and READDIR replies 39 * the length of v3 WRITE, READDIR and READDIR replies
40 * which are an RPC header, up to 26 XDR units of reply 40 * which are an RPC header, up to 26 XDR units of reply
41 * data, and some page data. 41 * data, and some page data.
42 * 42 *
43 * Note that accuracy here doesn't matter too much as the 43 * Note that accuracy here doesn't matter too much as the
44 * size is rounded up to a page size when allocating space. 44 * size is rounded up to a page size when allocating space.
45 */ 45 */
46 #define NFSD_BUFSIZE ((RPC_MAX_HEADER_WITH_AUTH+26)*XDR_UNIT + NFSSVC_MAXBLKSIZE) 46 #define NFSD_BUFSIZE ((RPC_MAX_HEADER_WITH_AUTH+26)*XDR_UNIT + NFSSVC_MAXBLKSIZE)
47 47
48 struct readdir_cd { 48 struct readdir_cd {
49 __be32 err; /* 0, nfserr, or nfserr_eof */ 49 __be32 err; /* 0, nfserr, or nfserr_eof */
50 }; 50 };
51 51
52 52
53 extern struct svc_program nfsd_program; 53 extern struct svc_program nfsd_program;
54 extern struct svc_version nfsd_version2, nfsd_version3, 54 extern struct svc_version nfsd_version2, nfsd_version3,
55 nfsd_version4; 55 nfsd_version4;
56 extern u32 nfsd_supported_minorversion; 56 extern u32 nfsd_supported_minorversion;
57 extern struct mutex nfsd_mutex; 57 extern struct mutex nfsd_mutex;
58 extern struct svc_serv *nfsd_serv; 58 extern struct svc_serv *nfsd_serv;
59 extern spinlock_t nfsd_drc_lock; 59 extern spinlock_t nfsd_drc_lock;
60 extern unsigned int nfsd_drc_max_mem; 60 extern unsigned int nfsd_drc_max_mem;
61 extern unsigned int nfsd_drc_mem_used; 61 extern unsigned int nfsd_drc_mem_used;
62 62
63 extern const struct seq_operations nfs_exports_op; 63 extern const struct seq_operations nfs_exports_op;
64 64
65 /* 65 /*
66 * Function prototypes. 66 * Function prototypes.
67 */ 67 */
68 int nfsd_svc(unsigned short port, int nrservs); 68 int nfsd_svc(unsigned short port, int nrservs);
69 int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); 69 int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
70 70
71 int nfsd_nrthreads(void); 71 int nfsd_nrthreads(void);
72 int nfsd_nrpools(void); 72 int nfsd_nrpools(void);
73 int nfsd_get_nrthreads(int n, int *); 73 int nfsd_get_nrthreads(int n, int *);
74 int nfsd_set_nrthreads(int n, int *); 74 int nfsd_set_nrthreads(int n, int *);
75 75
76 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 76 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
77 #ifdef CONFIG_NFSD_V2_ACL 77 #ifdef CONFIG_NFSD_V2_ACL
78 extern struct svc_version nfsd_acl_version2; 78 extern struct svc_version nfsd_acl_version2;
79 #else 79 #else
80 #define nfsd_acl_version2 NULL 80 #define nfsd_acl_version2 NULL
81 #endif 81 #endif
82 #ifdef CONFIG_NFSD_V3_ACL 82 #ifdef CONFIG_NFSD_V3_ACL
83 extern struct svc_version nfsd_acl_version3; 83 extern struct svc_version nfsd_acl_version3;
84 #else 84 #else
85 #define nfsd_acl_version3 NULL 85 #define nfsd_acl_version3 NULL
86 #endif 86 #endif
87 #endif 87 #endif
88 88
89 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; 89 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
90 int nfsd_vers(int vers, enum vers_op change); 90 int nfsd_vers(int vers, enum vers_op change);
91 int nfsd_minorversion(u32 minorversion, enum vers_op change); 91 int nfsd_minorversion(u32 minorversion, enum vers_op change);
92 void nfsd_reset_versions(void); 92 void nfsd_reset_versions(void);
93 int nfsd_create_serv(void); 93 int nfsd_create_serv(void);
94 94
95 extern int nfsd_max_blksize; 95 extern int nfsd_max_blksize;
96 96
97 static inline int nfsd_v4client(struct svc_rqst *rq) 97 static inline int nfsd_v4client(struct svc_rqst *rq)
98 { 98 {
99 return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4; 99 return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
100 } 100 }
101 101
102 /* 102 /*
103 * NFSv4 State 103 * NFSv4 State
104 */ 104 */
105 #ifdef CONFIG_NFSD_V4 105 #ifdef CONFIG_NFSD_V4
106 extern unsigned int max_delegations; 106 extern unsigned int max_delegations;
107 void nfs4_state_init(void); 107 void nfs4_state_init(void);
108 int nfsd4_init_slabs(void); 108 int nfsd4_init_slabs(void);
109 void nfsd4_free_slabs(void); 109 void nfsd4_free_slabs(void);
110 int nfs4_state_start(void); 110 int nfs4_state_start(void);
111 void nfs4_state_shutdown(void); 111 void nfs4_state_shutdown(void);
112 void nfs4_reset_lease(time_t leasetime); 112 void nfs4_reset_lease(time_t leasetime);
113 int nfs4_reset_recoverydir(char *recdir); 113 int nfs4_reset_recoverydir(char *recdir);
114 #else 114 #else
115 static inline void nfs4_state_init(void) { } 115 static inline void nfs4_state_init(void) { }
116 static inline int nfsd4_init_slabs(void) { return 0; } 116 static inline int nfsd4_init_slabs(void) { return 0; }
117 static inline void nfsd4_free_slabs(void) { } 117 static inline void nfsd4_free_slabs(void) { }
118 static inline int nfs4_state_start(void) { return 0; } 118 static inline int nfs4_state_start(void) { return 0; }
119 static inline void nfs4_state_shutdown(void) { } 119 static inline void nfs4_state_shutdown(void) { }
120 static inline void nfs4_reset_lease(time_t leasetime) { } 120 static inline void nfs4_reset_lease(time_t leasetime) { }
121 static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } 121 static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
122 #endif 122 #endif
123 123
124 /* 124 /*
125 * lockd binding 125 * lockd binding
126 */ 126 */
127 void nfsd_lockd_init(void); 127 void nfsd_lockd_init(void);
128 void nfsd_lockd_shutdown(void); 128 void nfsd_lockd_shutdown(void);
129 129
130 130
131 /* 131 /*
132 * These macros provide pre-xdr'ed values for faster operation. 132 * These macros provide pre-xdr'ed values for faster operation.
133 */ 133 */
134 #define nfs_ok cpu_to_be32(NFS_OK) 134 #define nfs_ok cpu_to_be32(NFS_OK)
135 #define nfserr_perm cpu_to_be32(NFSERR_PERM) 135 #define nfserr_perm cpu_to_be32(NFSERR_PERM)
136 #define nfserr_noent cpu_to_be32(NFSERR_NOENT) 136 #define nfserr_noent cpu_to_be32(NFSERR_NOENT)
137 #define nfserr_io cpu_to_be32(NFSERR_IO) 137 #define nfserr_io cpu_to_be32(NFSERR_IO)
138 #define nfserr_nxio cpu_to_be32(NFSERR_NXIO) 138 #define nfserr_nxio cpu_to_be32(NFSERR_NXIO)
139 #define nfserr_eagain cpu_to_be32(NFSERR_EAGAIN) 139 #define nfserr_eagain cpu_to_be32(NFSERR_EAGAIN)
140 #define nfserr_acces cpu_to_be32(NFSERR_ACCES) 140 #define nfserr_acces cpu_to_be32(NFSERR_ACCES)
141 #define nfserr_exist cpu_to_be32(NFSERR_EXIST) 141 #define nfserr_exist cpu_to_be32(NFSERR_EXIST)
142 #define nfserr_xdev cpu_to_be32(NFSERR_XDEV) 142 #define nfserr_xdev cpu_to_be32(NFSERR_XDEV)
143 #define nfserr_nodev cpu_to_be32(NFSERR_NODEV) 143 #define nfserr_nodev cpu_to_be32(NFSERR_NODEV)
144 #define nfserr_notdir cpu_to_be32(NFSERR_NOTDIR) 144 #define nfserr_notdir cpu_to_be32(NFSERR_NOTDIR)
145 #define nfserr_isdir cpu_to_be32(NFSERR_ISDIR) 145 #define nfserr_isdir cpu_to_be32(NFSERR_ISDIR)
146 #define nfserr_inval cpu_to_be32(NFSERR_INVAL) 146 #define nfserr_inval cpu_to_be32(NFSERR_INVAL)
147 #define nfserr_fbig cpu_to_be32(NFSERR_FBIG) 147 #define nfserr_fbig cpu_to_be32(NFSERR_FBIG)
148 #define nfserr_nospc cpu_to_be32(NFSERR_NOSPC) 148 #define nfserr_nospc cpu_to_be32(NFSERR_NOSPC)
149 #define nfserr_rofs cpu_to_be32(NFSERR_ROFS) 149 #define nfserr_rofs cpu_to_be32(NFSERR_ROFS)
150 #define nfserr_mlink cpu_to_be32(NFSERR_MLINK) 150 #define nfserr_mlink cpu_to_be32(NFSERR_MLINK)
151 #define nfserr_opnotsupp cpu_to_be32(NFSERR_OPNOTSUPP) 151 #define nfserr_opnotsupp cpu_to_be32(NFSERR_OPNOTSUPP)
152 #define nfserr_nametoolong cpu_to_be32(NFSERR_NAMETOOLONG) 152 #define nfserr_nametoolong cpu_to_be32(NFSERR_NAMETOOLONG)
153 #define nfserr_notempty cpu_to_be32(NFSERR_NOTEMPTY) 153 #define nfserr_notempty cpu_to_be32(NFSERR_NOTEMPTY)
154 #define nfserr_dquot cpu_to_be32(NFSERR_DQUOT) 154 #define nfserr_dquot cpu_to_be32(NFSERR_DQUOT)
155 #define nfserr_stale cpu_to_be32(NFSERR_STALE) 155 #define nfserr_stale cpu_to_be32(NFSERR_STALE)
156 #define nfserr_remote cpu_to_be32(NFSERR_REMOTE) 156 #define nfserr_remote cpu_to_be32(NFSERR_REMOTE)
157 #define nfserr_wflush cpu_to_be32(NFSERR_WFLUSH) 157 #define nfserr_wflush cpu_to_be32(NFSERR_WFLUSH)
158 #define nfserr_badhandle cpu_to_be32(NFSERR_BADHANDLE) 158 #define nfserr_badhandle cpu_to_be32(NFSERR_BADHANDLE)
159 #define nfserr_notsync cpu_to_be32(NFSERR_NOT_SYNC) 159 #define nfserr_notsync cpu_to_be32(NFSERR_NOT_SYNC)
160 #define nfserr_badcookie cpu_to_be32(NFSERR_BAD_COOKIE) 160 #define nfserr_badcookie cpu_to_be32(NFSERR_BAD_COOKIE)
161 #define nfserr_notsupp cpu_to_be32(NFSERR_NOTSUPP) 161 #define nfserr_notsupp cpu_to_be32(NFSERR_NOTSUPP)
162 #define nfserr_toosmall cpu_to_be32(NFSERR_TOOSMALL) 162 #define nfserr_toosmall cpu_to_be32(NFSERR_TOOSMALL)
163 #define nfserr_serverfault cpu_to_be32(NFSERR_SERVERFAULT) 163 #define nfserr_serverfault cpu_to_be32(NFSERR_SERVERFAULT)
164 #define nfserr_badtype cpu_to_be32(NFSERR_BADTYPE) 164 #define nfserr_badtype cpu_to_be32(NFSERR_BADTYPE)
165 #define nfserr_jukebox cpu_to_be32(NFSERR_JUKEBOX) 165 #define nfserr_jukebox cpu_to_be32(NFSERR_JUKEBOX)
166 #define nfserr_denied cpu_to_be32(NFSERR_DENIED) 166 #define nfserr_denied cpu_to_be32(NFSERR_DENIED)
167 #define nfserr_deadlock cpu_to_be32(NFSERR_DEADLOCK) 167 #define nfserr_deadlock cpu_to_be32(NFSERR_DEADLOCK)
168 #define nfserr_expired cpu_to_be32(NFSERR_EXPIRED) 168 #define nfserr_expired cpu_to_be32(NFSERR_EXPIRED)
169 #define nfserr_bad_cookie cpu_to_be32(NFSERR_BAD_COOKIE) 169 #define nfserr_bad_cookie cpu_to_be32(NFSERR_BAD_COOKIE)
170 #define nfserr_same cpu_to_be32(NFSERR_SAME) 170 #define nfserr_same cpu_to_be32(NFSERR_SAME)
171 #define nfserr_clid_inuse cpu_to_be32(NFSERR_CLID_INUSE) 171 #define nfserr_clid_inuse cpu_to_be32(NFSERR_CLID_INUSE)
172 #define nfserr_stale_clientid cpu_to_be32(NFSERR_STALE_CLIENTID) 172 #define nfserr_stale_clientid cpu_to_be32(NFSERR_STALE_CLIENTID)
173 #define nfserr_resource cpu_to_be32(NFSERR_RESOURCE) 173 #define nfserr_resource cpu_to_be32(NFSERR_RESOURCE)
174 #define nfserr_moved cpu_to_be32(NFSERR_MOVED) 174 #define nfserr_moved cpu_to_be32(NFSERR_MOVED)
175 #define nfserr_nofilehandle cpu_to_be32(NFSERR_NOFILEHANDLE) 175 #define nfserr_nofilehandle cpu_to_be32(NFSERR_NOFILEHANDLE)
176 #define nfserr_minor_vers_mismatch cpu_to_be32(NFSERR_MINOR_VERS_MISMATCH) 176 #define nfserr_minor_vers_mismatch cpu_to_be32(NFSERR_MINOR_VERS_MISMATCH)
177 #define nfserr_share_denied cpu_to_be32(NFSERR_SHARE_DENIED) 177 #define nfserr_share_denied cpu_to_be32(NFSERR_SHARE_DENIED)
178 #define nfserr_stale_stateid cpu_to_be32(NFSERR_STALE_STATEID) 178 #define nfserr_stale_stateid cpu_to_be32(NFSERR_STALE_STATEID)
179 #define nfserr_old_stateid cpu_to_be32(NFSERR_OLD_STATEID) 179 #define nfserr_old_stateid cpu_to_be32(NFSERR_OLD_STATEID)
180 #define nfserr_bad_stateid cpu_to_be32(NFSERR_BAD_STATEID) 180 #define nfserr_bad_stateid cpu_to_be32(NFSERR_BAD_STATEID)
181 #define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID) 181 #define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID)
182 #define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK) 182 #define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK)
183 #define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME) 183 #define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME)
184 #define nfserr_lock_range cpu_to_be32(NFSERR_LOCK_RANGE) 184 #define nfserr_lock_range cpu_to_be32(NFSERR_LOCK_RANGE)
185 #define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH) 185 #define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH)
186 #define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP) 186 #define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP)
187 #define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR) 187 #define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR)
188 #define nfserr_openmode cpu_to_be32(NFSERR_OPENMODE) 188 #define nfserr_openmode cpu_to_be32(NFSERR_OPENMODE)
189 #define nfserr_badowner cpu_to_be32(NFSERR_BADOWNER) 189 #define nfserr_badowner cpu_to_be32(NFSERR_BADOWNER)
190 #define nfserr_locks_held cpu_to_be32(NFSERR_LOCKS_HELD) 190 #define nfserr_locks_held cpu_to_be32(NFSERR_LOCKS_HELD)
191 #define nfserr_op_illegal cpu_to_be32(NFSERR_OP_ILLEGAL) 191 #define nfserr_op_illegal cpu_to_be32(NFSERR_OP_ILLEGAL)
192 #define nfserr_grace cpu_to_be32(NFSERR_GRACE) 192 #define nfserr_grace cpu_to_be32(NFSERR_GRACE)
193 #define nfserr_no_grace cpu_to_be32(NFSERR_NO_GRACE) 193 #define nfserr_no_grace cpu_to_be32(NFSERR_NO_GRACE)
194 #define nfserr_reclaim_bad cpu_to_be32(NFSERR_RECLAIM_BAD) 194 #define nfserr_reclaim_bad cpu_to_be32(NFSERR_RECLAIM_BAD)
195 #define nfserr_badname cpu_to_be32(NFSERR_BADNAME) 195 #define nfserr_badname cpu_to_be32(NFSERR_BADNAME)
196 #define nfserr_cb_path_down cpu_to_be32(NFSERR_CB_PATH_DOWN) 196 #define nfserr_cb_path_down cpu_to_be32(NFSERR_CB_PATH_DOWN)
197 #define nfserr_locked cpu_to_be32(NFSERR_LOCKED) 197 #define nfserr_locked cpu_to_be32(NFSERR_LOCKED)
198 #define nfserr_wrongsec cpu_to_be32(NFSERR_WRONGSEC) 198 #define nfserr_wrongsec cpu_to_be32(NFSERR_WRONGSEC)
199 #define nfserr_badiomode cpu_to_be32(NFS4ERR_BADIOMODE) 199 #define nfserr_badiomode cpu_to_be32(NFS4ERR_BADIOMODE)
200 #define nfserr_badlayout cpu_to_be32(NFS4ERR_BADLAYOUT) 200 #define nfserr_badlayout cpu_to_be32(NFS4ERR_BADLAYOUT)
201 #define nfserr_bad_session_digest cpu_to_be32(NFS4ERR_BAD_SESSION_DIGEST) 201 #define nfserr_bad_session_digest cpu_to_be32(NFS4ERR_BAD_SESSION_DIGEST)
202 #define nfserr_badsession cpu_to_be32(NFS4ERR_BADSESSION) 202 #define nfserr_badsession cpu_to_be32(NFS4ERR_BADSESSION)
203 #define nfserr_badslot cpu_to_be32(NFS4ERR_BADSLOT) 203 #define nfserr_badslot cpu_to_be32(NFS4ERR_BADSLOT)
204 #define nfserr_complete_already cpu_to_be32(NFS4ERR_COMPLETE_ALREADY) 204 #define nfserr_complete_already cpu_to_be32(NFS4ERR_COMPLETE_ALREADY)
205 #define nfserr_conn_not_bound_to_session cpu_to_be32(NFS4ERR_CONN_NOT_BOUND_TO_SESSION) 205 #define nfserr_conn_not_bound_to_session cpu_to_be32(NFS4ERR_CONN_NOT_BOUND_TO_SESSION)
206 #define nfserr_deleg_already_wanted cpu_to_be32(NFS4ERR_DELEG_ALREADY_WANTED) 206 #define nfserr_deleg_already_wanted cpu_to_be32(NFS4ERR_DELEG_ALREADY_WANTED)
207 #define nfserr_back_chan_busy cpu_to_be32(NFS4ERR_BACK_CHAN_BUSY) 207 #define nfserr_back_chan_busy cpu_to_be32(NFS4ERR_BACK_CHAN_BUSY)
208 #define nfserr_layouttrylater cpu_to_be32(NFS4ERR_LAYOUTTRYLATER) 208 #define nfserr_layouttrylater cpu_to_be32(NFS4ERR_LAYOUTTRYLATER)
209 #define nfserr_layoutunavailable cpu_to_be32(NFS4ERR_LAYOUTUNAVAILABLE) 209 #define nfserr_layoutunavailable cpu_to_be32(NFS4ERR_LAYOUTUNAVAILABLE)
210 #define nfserr_nomatching_layout cpu_to_be32(NFS4ERR_NOMATCHING_LAYOUT) 210 #define nfserr_nomatching_layout cpu_to_be32(NFS4ERR_NOMATCHING_LAYOUT)
211 #define nfserr_recallconflict cpu_to_be32(NFS4ERR_RECALLCONFLICT) 211 #define nfserr_recallconflict cpu_to_be32(NFS4ERR_RECALLCONFLICT)
212 #define nfserr_unknown_layouttype cpu_to_be32(NFS4ERR_UNKNOWN_LAYOUTTYPE) 212 #define nfserr_unknown_layouttype cpu_to_be32(NFS4ERR_UNKNOWN_LAYOUTTYPE)
213 #define nfserr_seq_misordered cpu_to_be32(NFS4ERR_SEQ_MISORDERED) 213 #define nfserr_seq_misordered cpu_to_be32(NFS4ERR_SEQ_MISORDERED)
214 #define nfserr_sequence_pos cpu_to_be32(NFS4ERR_SEQUENCE_POS) 214 #define nfserr_sequence_pos cpu_to_be32(NFS4ERR_SEQUENCE_POS)
215 #define nfserr_req_too_big cpu_to_be32(NFS4ERR_REQ_TOO_BIG) 215 #define nfserr_req_too_big cpu_to_be32(NFS4ERR_REQ_TOO_BIG)
216 #define nfserr_rep_too_big cpu_to_be32(NFS4ERR_REP_TOO_BIG) 216 #define nfserr_rep_too_big cpu_to_be32(NFS4ERR_REP_TOO_BIG)
217 #define nfserr_rep_too_big_to_cache cpu_to_be32(NFS4ERR_REP_TOO_BIG_TO_CACHE) 217 #define nfserr_rep_too_big_to_cache cpu_to_be32(NFS4ERR_REP_TOO_BIG_TO_CACHE)
218 #define nfserr_retry_uncached_rep cpu_to_be32(NFS4ERR_RETRY_UNCACHED_REP) 218 #define nfserr_retry_uncached_rep cpu_to_be32(NFS4ERR_RETRY_UNCACHED_REP)
219 #define nfserr_unsafe_compound cpu_to_be32(NFS4ERR_UNSAFE_COMPOUND) 219 #define nfserr_unsafe_compound cpu_to_be32(NFS4ERR_UNSAFE_COMPOUND)
220 #define nfserr_too_many_ops cpu_to_be32(NFS4ERR_TOO_MANY_OPS) 220 #define nfserr_too_many_ops cpu_to_be32(NFS4ERR_TOO_MANY_OPS)
221 #define nfserr_op_not_in_session cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION) 221 #define nfserr_op_not_in_session cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION)
222 #define nfserr_hash_alg_unsupp cpu_to_be32(NFS4ERR_HASH_ALG_UNSUPP) 222 #define nfserr_hash_alg_unsupp cpu_to_be32(NFS4ERR_HASH_ALG_UNSUPP)
223 #define nfserr_clientid_busy cpu_to_be32(NFS4ERR_CLIENTID_BUSY) 223 #define nfserr_clientid_busy cpu_to_be32(NFS4ERR_CLIENTID_BUSY)
224 #define nfserr_pnfs_io_hole cpu_to_be32(NFS4ERR_PNFS_IO_HOLE) 224 #define nfserr_pnfs_io_hole cpu_to_be32(NFS4ERR_PNFS_IO_HOLE)
225 #define nfserr_seq_false_retry cpu_to_be32(NFS4ERR_SEQ_FALSE_RETRY) 225 #define nfserr_seq_false_retry cpu_to_be32(NFS4ERR_SEQ_FALSE_RETRY)
226 #define nfserr_bad_high_slot cpu_to_be32(NFS4ERR_BAD_HIGH_SLOT) 226 #define nfserr_bad_high_slot cpu_to_be32(NFS4ERR_BAD_HIGH_SLOT)
227 #define nfserr_deadsession cpu_to_be32(NFS4ERR_DEADSESSION) 227 #define nfserr_deadsession cpu_to_be32(NFS4ERR_DEADSESSION)
228 #define nfserr_encr_alg_unsupp cpu_to_be32(NFS4ERR_ENCR_ALG_UNSUPP) 228 #define nfserr_encr_alg_unsupp cpu_to_be32(NFS4ERR_ENCR_ALG_UNSUPP)
229 #define nfserr_pnfs_no_layout cpu_to_be32(NFS4ERR_PNFS_NO_LAYOUT) 229 #define nfserr_pnfs_no_layout cpu_to_be32(NFS4ERR_PNFS_NO_LAYOUT)
230 #define nfserr_not_only_op cpu_to_be32(NFS4ERR_NOT_ONLY_OP) 230 #define nfserr_not_only_op cpu_to_be32(NFS4ERR_NOT_ONLY_OP)
231 #define nfserr_wrong_cred cpu_to_be32(NFS4ERR_WRONG_CRED) 231 #define nfserr_wrong_cred cpu_to_be32(NFS4ERR_WRONG_CRED)
232 #define nfserr_wrong_type cpu_to_be32(NFS4ERR_WRONG_TYPE) 232 #define nfserr_wrong_type cpu_to_be32(NFS4ERR_WRONG_TYPE)
233 #define nfserr_dirdeleg_unavail cpu_to_be32(NFS4ERR_DIRDELEG_UNAVAIL) 233 #define nfserr_dirdeleg_unavail cpu_to_be32(NFS4ERR_DIRDELEG_UNAVAIL)
234 #define nfserr_reject_deleg cpu_to_be32(NFS4ERR_REJECT_DELEG) 234 #define nfserr_reject_deleg cpu_to_be32(NFS4ERR_REJECT_DELEG)
235 #define nfserr_returnconflict cpu_to_be32(NFS4ERR_RETURNCONFLICT) 235 #define nfserr_returnconflict cpu_to_be32(NFS4ERR_RETURNCONFLICT)
236 #define nfserr_deleg_revoked cpu_to_be32(NFS4ERR_DELEG_REVOKED) 236 #define nfserr_deleg_revoked cpu_to_be32(NFS4ERR_DELEG_REVOKED)
237 237
238 /* error codes for internal use */ 238 /* error codes for internal use */
239 /* if a request fails due to kmalloc failure, it gets dropped. 239 /* if a request fails due to kmalloc failure, it gets dropped.
240 * Client should resend eventually 240 * Client should resend eventually
241 */ 241 */
242 #define nfserr_dropit cpu_to_be32(30000) 242 #define nfserr_dropit cpu_to_be32(30000)
243 /* end-of-file indicator in readdir */ 243 /* end-of-file indicator in readdir */
244 #define nfserr_eof cpu_to_be32(30001) 244 #define nfserr_eof cpu_to_be32(30001)
245 /* replay detected */ 245 /* replay detected */
246 #define nfserr_replay_me cpu_to_be32(11001) 246 #define nfserr_replay_me cpu_to_be32(11001)
247 /* nfs41 replay detected */ 247 /* nfs41 replay detected */
248 #define nfserr_replay_cache cpu_to_be32(11002) 248 #define nfserr_replay_cache cpu_to_be32(11002)
249 249
250 /* Check for dir entries '.' and '..' */ 250 /* Check for dir entries '.' and '..' */
251 #define isdotent(n, l) (l < 3 && n[0] == '.' && (l == 1 || n[1] == '.')) 251 #define isdotent(n, l) (l < 3 && n[0] == '.' && (l == 1 || n[1] == '.'))
252 252
253 /* 253 /*
254 * Time of server startup 254 * Time of server startup
255 */ 255 */
256 extern struct timeval nfssvc_boot; 256 extern struct timeval nfssvc_boot;
257 257
258 #ifdef CONFIG_NFSD_V4 258 #ifdef CONFIG_NFSD_V4
259 259
260 extern time_t nfsd4_lease; 260 extern time_t nfsd4_lease;
261 extern time_t nfsd4_grace; 261 extern time_t nfsd4_grace;
262 262
263 /* before processing a COMPOUND operation, we have to check that there 263 /* before processing a COMPOUND operation, we have to check that there
264 * is enough space in the buffer for XDR encode to succeed. otherwise, 264 * is enough space in the buffer for XDR encode to succeed. otherwise,
265 * we might process an operation with side effects, and be unable to 265 * we might process an operation with side effects, and be unable to
266 * tell the client that the operation succeeded. 266 * tell the client that the operation succeeded.
267 * 267 *
268 * COMPOUND_SLACK_SPACE - this is the minimum bytes of buffer space 268 * COMPOUND_SLACK_SPACE - this is the minimum bytes of buffer space
269 * needed to encode an "ordinary" _successful_ operation. (GETATTR, 269 * needed to encode an "ordinary" _successful_ operation. (GETATTR,
270 * READ, READDIR, and READLINK have their own buffer checks.) if we 270 * READ, READDIR, and READLINK have their own buffer checks.) if we
271 * fall below this level, we fail the next operation with NFS4ERR_RESOURCE. 271 * fall below this level, we fail the next operation with NFS4ERR_RESOURCE.
272 * 272 *
273 * COMPOUND_ERR_SLACK_SPACE - this is the minimum bytes of buffer space 273 * COMPOUND_ERR_SLACK_SPACE - this is the minimum bytes of buffer space
274 * needed to encode an operation which has failed with NFS4ERR_RESOURCE. 274 * needed to encode an operation which has failed with NFS4ERR_RESOURCE.
275 * care is taken to ensure that we never fall below this level for any 275 * care is taken to ensure that we never fall below this level for any
276 * reason. 276 * reason.
277 */ 277 */
278 #define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */ 278 #define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */
279 #define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */ 279 #define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */
280 280
281 #define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */ 281 #define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */
282 282
283 /* 283 /*
284 * The following attributes are currently not supported by the NFSv4 server: 284 * The following attributes are currently not supported by the NFSv4 server:
285 * ARCHIVE (deprecated anyway) 285 * ARCHIVE (deprecated anyway)
286 * HIDDEN (unlikely to be supported any time soon) 286 * HIDDEN (unlikely to be supported any time soon)
287 * MIMETYPE (unlikely to be supported any time soon) 287 * MIMETYPE (unlikely to be supported any time soon)
288 * QUOTA_* (will be supported in a forthcoming patch) 288 * QUOTA_* (will be supported in a forthcoming patch)
289 * SYSTEM (unlikely to be supported any time soon) 289 * SYSTEM (unlikely to be supported any time soon)
290 * TIME_BACKUP (unlikely to be supported any time soon) 290 * TIME_BACKUP (unlikely to be supported any time soon)
291 * TIME_CREATE (unlikely to be supported any time soon) 291 * TIME_CREATE (unlikely to be supported any time soon)
292 */ 292 */
293 #define NFSD4_SUPPORTED_ATTRS_WORD0 \ 293 #define NFSD4_SUPPORTED_ATTRS_WORD0 \
294 (FATTR4_WORD0_SUPPORTED_ATTRS | FATTR4_WORD0_TYPE | FATTR4_WORD0_FH_EXPIRE_TYPE \ 294 (FATTR4_WORD0_SUPPORTED_ATTRS | FATTR4_WORD0_TYPE | FATTR4_WORD0_FH_EXPIRE_TYPE \
295 | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE | FATTR4_WORD0_LINK_SUPPORT \ 295 | FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE | FATTR4_WORD0_LINK_SUPPORT \
296 | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR | FATTR4_WORD0_FSID \ 296 | FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_NAMED_ATTR | FATTR4_WORD0_FSID \
297 | FATTR4_WORD0_UNIQUE_HANDLES | FATTR4_WORD0_LEASE_TIME | FATTR4_WORD0_RDATTR_ERROR \ 297 | FATTR4_WORD0_UNIQUE_HANDLES | FATTR4_WORD0_LEASE_TIME | FATTR4_WORD0_RDATTR_ERROR \
298 | FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_CANSETTIME | FATTR4_WORD0_CASE_INSENSITIVE \ 298 | FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_CANSETTIME | FATTR4_WORD0_CASE_INSENSITIVE \
299 | FATTR4_WORD0_CASE_PRESERVING | FATTR4_WORD0_CHOWN_RESTRICTED \ 299 | FATTR4_WORD0_CASE_PRESERVING | FATTR4_WORD0_CHOWN_RESTRICTED \
300 | FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FILEID | FATTR4_WORD0_FILES_AVAIL \ 300 | FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FILEID | FATTR4_WORD0_FILES_AVAIL \
301 | FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_HOMOGENEOUS \ 301 | FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_HOMOGENEOUS \
302 | FATTR4_WORD0_MAXFILESIZE | FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME \ 302 | FATTR4_WORD0_MAXFILESIZE | FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME \
303 | FATTR4_WORD0_MAXREAD | FATTR4_WORD0_MAXWRITE | FATTR4_WORD0_ACL) 303 | FATTR4_WORD0_MAXREAD | FATTR4_WORD0_MAXWRITE | FATTR4_WORD0_ACL)
304 304
305 #define NFSD4_SUPPORTED_ATTRS_WORD1 \ 305 #define NFSD4_SUPPORTED_ATTRS_WORD1 \
306 (FATTR4_WORD1_MODE | FATTR4_WORD1_NO_TRUNC | FATTR4_WORD1_NUMLINKS \ 306 (FATTR4_WORD1_MODE | FATTR4_WORD1_NO_TRUNC | FATTR4_WORD1_NUMLINKS \
307 | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \ 307 | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \
308 | FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \ 308 | FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \
309 | FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_ACCESS_SET \ 309 | FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_ACCESS_SET \
310 | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \ 310 | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \
311 | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID) 311 | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID)
312 312
313 #define NFSD4_SUPPORTED_ATTRS_WORD2 0 313 #define NFSD4_SUPPORTED_ATTRS_WORD2 0
314 314
315 #define NFSD4_1_SUPPORTED_ATTRS_WORD0 \ 315 #define NFSD4_1_SUPPORTED_ATTRS_WORD0 \
316 NFSD4_SUPPORTED_ATTRS_WORD0 316 NFSD4_SUPPORTED_ATTRS_WORD0
317 317
318 #define NFSD4_1_SUPPORTED_ATTRS_WORD1 \ 318 #define NFSD4_1_SUPPORTED_ATTRS_WORD1 \
319 NFSD4_SUPPORTED_ATTRS_WORD1 319 NFSD4_SUPPORTED_ATTRS_WORD1
320 320
321 #define NFSD4_1_SUPPORTED_ATTRS_WORD2 \ 321 #define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
322 (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) 322 (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
323 323
324 static inline u32 nfsd_suppattrs0(u32 minorversion) 324 static inline u32 nfsd_suppattrs0(u32 minorversion)
325 { 325 {
326 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 326 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
327 : NFSD4_SUPPORTED_ATTRS_WORD0; 327 : NFSD4_SUPPORTED_ATTRS_WORD0;
328 } 328 }
329 329
330 static inline u32 nfsd_suppattrs1(u32 minorversion) 330 static inline u32 nfsd_suppattrs1(u32 minorversion)
331 { 331 {
332 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1 332 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD1
333 : NFSD4_SUPPORTED_ATTRS_WORD1; 333 : NFSD4_SUPPORTED_ATTRS_WORD1;
334 } 334 }
335 335
336 static inline u32 nfsd_suppattrs2(u32 minorversion) 336 static inline u32 nfsd_suppattrs2(u32 minorversion)
337 { 337 {
338 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2 338 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2
339 : NFSD4_SUPPORTED_ATTRS_WORD2; 339 : NFSD4_SUPPORTED_ATTRS_WORD2;
340 } 340 }
341 341
342 /* These will return ERR_INVAL if specified in GETATTR or READDIR. */ 342 /* These will return ERR_INVAL if specified in GETATTR or READDIR. */
343 #define NFSD_WRITEONLY_ATTRS_WORD1 \ 343 #define NFSD_WRITEONLY_ATTRS_WORD1 \
344 (FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 344 (FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
345 345
346 /* These are the only attrs allowed in CREATE/OPEN/SETATTR. */ 346 /* These are the only attrs allowed in CREATE/OPEN/SETATTR. */
347 #define NFSD_WRITEABLE_ATTRS_WORD0 \ 347 #define NFSD_WRITEABLE_ATTRS_WORD0 \
348 (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL) 348 (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL)
349 #define NFSD_WRITEABLE_ATTRS_WORD1 \ 349 #define NFSD_WRITEABLE_ATTRS_WORD1 \
350 (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ 350 (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
351 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 351 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
352 #define NFSD_WRITEABLE_ATTRS_WORD2 0 352 #define NFSD_WRITEABLE_ATTRS_WORD2 0
353 353
354 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ 354 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
355 NFSD_WRITEABLE_ATTRS_WORD0 355 NFSD_WRITEABLE_ATTRS_WORD0
356 /* 356 /*
357 * we currently store the exclusive create verifier in the v_{a,m}time 357 * we currently store the exclusive create verifier in the v_{a,m}time
358 * attributes so the client can't set these at create time using EXCLUSIVE4_1 358 * attributes so the client can't set these at create time using EXCLUSIVE4_1
359 */ 359 */
360 #define NFSD_SUPPATTR_EXCLCREAT_WORD1 \ 360 #define NFSD_SUPPATTR_EXCLCREAT_WORD1 \
361 (NFSD_WRITEABLE_ATTRS_WORD1 & \ 361 (NFSD_WRITEABLE_ATTRS_WORD1 & \
362 ~(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)) 362 ~(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET))
363 #define NFSD_SUPPATTR_EXCLCREAT_WORD2 \ 363 #define NFSD_SUPPATTR_EXCLCREAT_WORD2 \
364 NFSD_WRITEABLE_ATTRS_WORD2 364 NFSD_WRITEABLE_ATTRS_WORD2
365 365
366 extern int nfsd4_is_junction(struct dentry *dentry); 366 extern int nfsd4_is_junction(struct dentry *dentry);
367 #else 367 extern int register_cld_notifier(void);
368 extern void unregister_cld_notifier(void);
369 #else /* CONFIG_NFSD_V4 */
368 static inline int nfsd4_is_junction(struct dentry *dentry) 370 static inline int nfsd4_is_junction(struct dentry *dentry)
369 { 371 {
370 return 0; 372 return 0;
371 } 373 }
374
375 #define register_cld_notifier() 0
376 #define unregister_cld_notifier() do { } while(0)
372 377
373 #endif /* CONFIG_NFSD_V4 */ 378 #endif /* CONFIG_NFSD_V4 */
374 379
375 #endif /* LINUX_NFSD_NFSD_H */ 380 #endif /* LINUX_NFSD_NFSD_H */
376 381