aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 13:22:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 13:22:40 -0400
commit5ed487bc2c44ca4e9668ef9cb54c830e2a9fac47 (patch)
treeaf19ed28db83e8f52690872ac99336da1cf2fd3b /fs/nfsd
parent5b34653963de7a6d0d8c783527457d68fddc60fb (diff)
parentfd217f4d70172c526478f2bc76859e909fdfa674 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (46 commits) [PATCH] fs: add a sanity check in d_free [PATCH] i_version: remount support [patch] vfs: make security_inode_setattr() calling consistent [patch 1/3] FS_MBCACHE: don't needlessly make it built-in [PATCH] move executable checking into ->permission() [PATCH] fs/dcache.c: update comment of d_validate() [RFC PATCH] touch_mnt_namespace when the mount flags change [PATCH] reiserfs: add missing llseek method [PATCH] fix ->llseek for more directories [PATCH vfs-2.6 6/6] vfs: add LOOKUP_RENAME_TARGET intent [PATCH vfs-2.6 5/6] vfs: remove LOOKUP_PARENT from non LOOKUP_PARENT lookup [PATCH vfs-2.6 4/6] vfs: remove unnecessary fsnotify_d_instantiate() [PATCH vfs-2.6 3/6] vfs: add __d_instantiate() helper [PATCH vfs-2.6 2/6] vfs: add d_ancestor() [PATCH vfs-2.6 1/6] vfs: replace parent == dentry->d_parent by IS_ROOT() [PATCH] get rid of on-stack dentry in udf [PATCH 2/2] anondev: switch to IDA [PATCH 1/2] anondev: init IDR statically [JFFS2] Use d_splice_alias() not d_add() in jffs2_lookup() [PATCH] Optimise NFS readdir hack slightly. ...
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c125
-rw-r--r--fs/nfsd/nfs4recover.c50
-rw-r--r--fs/nfsd/nfs4state.c8
-rw-r--r--fs/nfsd/nfsctl.c8
-rw-r--r--fs/nfsd/vfs.c126
5 files changed, 201 insertions, 116 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 5cd882b8871a..5839b229cd0e 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -163,18 +163,16 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
163 if (!ek) 163 if (!ek)
164 err = -ENOMEM; 164 err = -ENOMEM;
165 } else { 165 } else {
166 struct nameidata nd; 166 err = kern_path(buf, 0, &key.ek_path);
167 err = path_lookup(buf, 0, &nd);
168 if (err) 167 if (err)
169 goto out; 168 goto out;
170 169
171 dprintk("Found the path %s\n", buf); 170 dprintk("Found the path %s\n", buf);
172 key.ek_path = nd.path;
173 171
174 ek = svc_expkey_update(&key, ek); 172 ek = svc_expkey_update(&key, ek);
175 if (!ek) 173 if (!ek)
176 err = -ENOMEM; 174 err = -ENOMEM;
177 path_put(&nd.path); 175 path_put(&key.ek_path);
178 } 176 }
179 cache_flush(); 177 cache_flush();
180 out: 178 out:
@@ -501,35 +499,22 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
501 int len; 499 int len;
502 int err; 500 int err;
503 struct auth_domain *dom = NULL; 501 struct auth_domain *dom = NULL;
504 struct nameidata nd; 502 struct svc_export exp = {}, *expp;
505 struct svc_export exp, *expp;
506 int an_int; 503 int an_int;
507 504
508 nd.path.dentry = NULL;
509 exp.ex_pathname = NULL;
510
511 /* fs locations */
512 exp.ex_fslocs.locations = NULL;
513 exp.ex_fslocs.locations_count = 0;
514 exp.ex_fslocs.migrated = 0;
515
516 exp.ex_uuid = NULL;
517
518 /* secinfo */
519 exp.ex_nflavors = 0;
520
521 if (mesg[mlen-1] != '\n') 505 if (mesg[mlen-1] != '\n')
522 return -EINVAL; 506 return -EINVAL;
523 mesg[mlen-1] = 0; 507 mesg[mlen-1] = 0;
524 508
525 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 509 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
526 err = -ENOMEM; 510 if (!buf)
527 if (!buf) goto out; 511 return -ENOMEM;
528 512
529 /* client */ 513 /* client */
530 len = qword_get(&mesg, buf, PAGE_SIZE);
531 err = -EINVAL; 514 err = -EINVAL;
532 if (len <= 0) goto out; 515 len = qword_get(&mesg, buf, PAGE_SIZE);
516 if (len <= 0)
517 goto out;
533 518
534 err = -ENOENT; 519 err = -ENOENT;
535 dom = auth_domain_find(buf); 520 dom = auth_domain_find(buf);
@@ -538,25 +523,25 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
538 523
539 /* path */ 524 /* path */
540 err = -EINVAL; 525 err = -EINVAL;
541 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 526 if ((len = qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
542 goto out; 527 goto out1;
543 err = path_lookup(buf, 0, &nd); 528
544 if (err) goto out_no_path; 529 err = kern_path(buf, 0, &exp.ex_path);
530 if (err)
531 goto out1;
545 532
546 exp.h.flags = 0;
547 exp.ex_client = dom; 533 exp.ex_client = dom;
548 exp.ex_path.mnt = nd.path.mnt; 534
549 exp.ex_path.dentry = nd.path.dentry;
550 exp.ex_pathname = kstrdup(buf, GFP_KERNEL);
551 err = -ENOMEM; 535 err = -ENOMEM;
536 exp.ex_pathname = kstrdup(buf, GFP_KERNEL);
552 if (!exp.ex_pathname) 537 if (!exp.ex_pathname)
553 goto out; 538 goto out2;
554 539
555 /* expiry */ 540 /* expiry */
556 err = -EINVAL; 541 err = -EINVAL;
557 exp.h.expiry_time = get_expiry(&mesg); 542 exp.h.expiry_time = get_expiry(&mesg);
558 if (exp.h.expiry_time == 0) 543 if (exp.h.expiry_time == 0)
559 goto out; 544 goto out3;
560 545
561 /* flags */ 546 /* flags */
562 err = get_int(&mesg, &an_int); 547 err = get_int(&mesg, &an_int);
@@ -564,22 +549,26 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
564 err = 0; 549 err = 0;
565 set_bit(CACHE_NEGATIVE, &exp.h.flags); 550 set_bit(CACHE_NEGATIVE, &exp.h.flags);
566 } else { 551 } else {
567 if (err || an_int < 0) goto out; 552 if (err || an_int < 0)
553 goto out3;
568 exp.ex_flags= an_int; 554 exp.ex_flags= an_int;
569 555
570 /* anon uid */ 556 /* anon uid */
571 err = get_int(&mesg, &an_int); 557 err = get_int(&mesg, &an_int);
572 if (err) goto out; 558 if (err)
559 goto out3;
573 exp.ex_anon_uid= an_int; 560 exp.ex_anon_uid= an_int;
574 561
575 /* anon gid */ 562 /* anon gid */
576 err = get_int(&mesg, &an_int); 563 err = get_int(&mesg, &an_int);
577 if (err) goto out; 564 if (err)
565 goto out3;
578 exp.ex_anon_gid= an_int; 566 exp.ex_anon_gid= an_int;
579 567
580 /* fsid */ 568 /* fsid */
581 err = get_int(&mesg, &an_int); 569 err = get_int(&mesg, &an_int);
582 if (err) goto out; 570 if (err)
571 goto out3;
583 exp.ex_fsid = an_int; 572 exp.ex_fsid = an_int;
584 573
585 while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) { 574 while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
@@ -605,12 +594,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
605 */ 594 */
606 break; 595 break;
607 if (err) 596 if (err)
608 goto out; 597 goto out4;
609 } 598 }
610 599
611 err = check_export(nd.path.dentry->d_inode, exp.ex_flags, 600 err = check_export(exp.ex_path.dentry->d_inode, exp.ex_flags,
612 exp.ex_uuid); 601 exp.ex_uuid);
613 if (err) goto out; 602 if (err)
603 goto out4;
614 } 604 }
615 605
616 expp = svc_export_lookup(&exp); 606 expp = svc_export_lookup(&exp);
@@ -623,15 +613,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
623 err = -ENOMEM; 613 err = -ENOMEM;
624 else 614 else
625 exp_put(expp); 615 exp_put(expp);
626 out: 616out4:
627 nfsd4_fslocs_free(&exp.ex_fslocs); 617 nfsd4_fslocs_free(&exp.ex_fslocs);
628 kfree(exp.ex_uuid); 618 kfree(exp.ex_uuid);
619out3:
629 kfree(exp.ex_pathname); 620 kfree(exp.ex_pathname);
630 if (nd.path.dentry) 621out2:
631 path_put(&nd.path); 622 path_put(&exp.ex_path);
632 out_no_path: 623out1:
633 if (dom) 624 auth_domain_put(dom);
634 auth_domain_put(dom); 625out:
635 kfree(buf); 626 kfree(buf);
636 return err; 627 return err;
637} 628}
@@ -999,7 +990,7 @@ exp_export(struct nfsctl_export *nxp)
999 struct svc_export *exp = NULL; 990 struct svc_export *exp = NULL;
1000 struct svc_export new; 991 struct svc_export new;
1001 struct svc_expkey *fsid_key = NULL; 992 struct svc_expkey *fsid_key = NULL;
1002 struct nameidata nd; 993 struct path path;
1003 int err; 994 int err;
1004 995
1005 /* Consistency check */ 996 /* Consistency check */
@@ -1022,12 +1013,12 @@ exp_export(struct nfsctl_export *nxp)
1022 1013
1023 1014
1024 /* Look up the dentry */ 1015 /* Look up the dentry */
1025 err = path_lookup(nxp->ex_path, 0, &nd); 1016 err = kern_path(nxp->ex_path, 0, &path);
1026 if (err) 1017 if (err)
1027 goto out_put_clp; 1018 goto out_put_clp;
1028 err = -EINVAL; 1019 err = -EINVAL;
1029 1020
1030 exp = exp_get_by_name(clp, nd.path.mnt, nd.path.dentry, NULL); 1021 exp = exp_get_by_name(clp, path.mnt, path.dentry, NULL);
1031 1022
1032 memset(&new, 0, sizeof(new)); 1023 memset(&new, 0, sizeof(new));
1033 1024
@@ -1035,8 +1026,8 @@ exp_export(struct nfsctl_export *nxp)
1035 if ((nxp->ex_flags & NFSEXP_FSID) && 1026 if ((nxp->ex_flags & NFSEXP_FSID) &&
1036 (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) && 1027 (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
1037 fsid_key->ek_path.mnt && 1028 fsid_key->ek_path.mnt &&
1038 (fsid_key->ek_path.mnt != nd.path.mnt || 1029 (fsid_key->ek_path.mnt != path.mnt ||
1039 fsid_key->ek_path.dentry != nd.path.dentry)) 1030 fsid_key->ek_path.dentry != path.dentry))
1040 goto finish; 1031 goto finish;
1041 1032
1042 if (!IS_ERR(exp)) { 1033 if (!IS_ERR(exp)) {
@@ -1052,7 +1043,7 @@ exp_export(struct nfsctl_export *nxp)
1052 goto finish; 1043 goto finish;
1053 } 1044 }
1054 1045
1055 err = check_export(nd.path.dentry->d_inode, nxp->ex_flags, NULL); 1046 err = check_export(path.dentry->d_inode, nxp->ex_flags, NULL);
1056 if (err) goto finish; 1047 if (err) goto finish;
1057 1048
1058 err = -ENOMEM; 1049 err = -ENOMEM;
@@ -1065,7 +1056,7 @@ exp_export(struct nfsctl_export *nxp)
1065 if (!new.ex_pathname) 1056 if (!new.ex_pathname)
1066 goto finish; 1057 goto finish;
1067 new.ex_client = clp; 1058 new.ex_client = clp;
1068 new.ex_path = nd.path; 1059 new.ex_path = path;
1069 new.ex_flags = nxp->ex_flags; 1060 new.ex_flags = nxp->ex_flags;
1070 new.ex_anon_uid = nxp->ex_anon_uid; 1061 new.ex_anon_uid = nxp->ex_anon_uid;
1071 new.ex_anon_gid = nxp->ex_anon_gid; 1062 new.ex_anon_gid = nxp->ex_anon_gid;
@@ -1091,7 +1082,7 @@ finish:
1091 exp_put(exp); 1082 exp_put(exp);
1092 if (fsid_key && !IS_ERR(fsid_key)) 1083 if (fsid_key && !IS_ERR(fsid_key))
1093 cache_put(&fsid_key->h, &svc_expkey_cache); 1084 cache_put(&fsid_key->h, &svc_expkey_cache);
1094 path_put(&nd.path); 1085 path_put(&path);
1095out_put_clp: 1086out_put_clp:
1096 auth_domain_put(clp); 1087 auth_domain_put(clp);
1097out_unlock: 1088out_unlock:
@@ -1122,7 +1113,7 @@ exp_unexport(struct nfsctl_export *nxp)
1122{ 1113{
1123 struct auth_domain *dom; 1114 struct auth_domain *dom;
1124 svc_export *exp; 1115 svc_export *exp;
1125 struct nameidata nd; 1116 struct path path;
1126 int err; 1117 int err;
1127 1118
1128 /* Consistency check */ 1119 /* Consistency check */
@@ -1139,13 +1130,13 @@ exp_unexport(struct nfsctl_export *nxp)
1139 goto out_unlock; 1130 goto out_unlock;
1140 } 1131 }
1141 1132
1142 err = path_lookup(nxp->ex_path, 0, &nd); 1133 err = kern_path(nxp->ex_path, 0, &path);
1143 if (err) 1134 if (err)
1144 goto out_domain; 1135 goto out_domain;
1145 1136
1146 err = -EINVAL; 1137 err = -EINVAL;
1147 exp = exp_get_by_name(dom, nd.path.mnt, nd.path.dentry, NULL); 1138 exp = exp_get_by_name(dom, path.mnt, path.dentry, NULL);
1148 path_put(&nd.path); 1139 path_put(&path);
1149 if (IS_ERR(exp)) 1140 if (IS_ERR(exp))
1150 goto out_domain; 1141 goto out_domain;
1151 1142
@@ -1167,26 +1158,26 @@ out_unlock:
1167 * since its harder to fool a kernel module than a user space program. 1158 * since its harder to fool a kernel module than a user space program.
1168 */ 1159 */
1169int 1160int
1170exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) 1161exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
1171{ 1162{
1172 struct svc_export *exp; 1163 struct svc_export *exp;
1173 struct nameidata nd; 1164 struct path path;
1174 struct inode *inode; 1165 struct inode *inode;
1175 struct svc_fh fh; 1166 struct svc_fh fh;
1176 int err; 1167 int err;
1177 1168
1178 err = -EPERM; 1169 err = -EPERM;
1179 /* NB: we probably ought to check that it's NUL-terminated */ 1170 /* NB: we probably ought to check that it's NUL-terminated */
1180 if (path_lookup(path, 0, &nd)) { 1171 if (kern_path(name, 0, &path)) {
1181 printk("nfsd: exp_rootfh path not found %s", path); 1172 printk("nfsd: exp_rootfh path not found %s", name);
1182 return err; 1173 return err;
1183 } 1174 }
1184 inode = nd.path.dentry->d_inode; 1175 inode = path.dentry->d_inode;
1185 1176
1186 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", 1177 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
1187 path, nd.path.dentry, clp->name, 1178 name, path.dentry, clp->name,
1188 inode->i_sb->s_id, inode->i_ino); 1179 inode->i_sb->s_id, inode->i_ino);
1189 exp = exp_parent(clp, nd.path.mnt, nd.path.dentry, NULL); 1180 exp = exp_parent(clp, path.mnt, path.dentry, NULL);
1190 if (IS_ERR(exp)) { 1181 if (IS_ERR(exp)) {
1191 err = PTR_ERR(exp); 1182 err = PTR_ERR(exp);
1192 goto out; 1183 goto out;
@@ -1196,7 +1187,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
1196 * fh must be initialized before calling fh_compose 1187 * fh must be initialized before calling fh_compose
1197 */ 1188 */
1198 fh_init(&fh, maxsize); 1189 fh_init(&fh, maxsize);
1199 if (fh_compose(&fh, exp, nd.path.dentry, NULL)) 1190 if (fh_compose(&fh, exp, path.dentry, NULL))
1200 err = -EINVAL; 1191 err = -EINVAL;
1201 else 1192 else
1202 err = 0; 1193 err = 0;
@@ -1204,7 +1195,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
1204 fh_put(&fh); 1195 fh_put(&fh);
1205 exp_put(exp); 1196 exp_put(exp);
1206out: 1197out:
1207 path_put(&nd.path); 1198 path_put(&path);
1208 return err; 1199 return err;
1209} 1200}
1210 1201
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 145b3c877a27..bb93946ace22 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -51,7 +51,7 @@
51#define NFSDDBG_FACILITY NFSDDBG_PROC 51#define NFSDDBG_FACILITY NFSDDBG_PROC
52 52
53/* Globals */ 53/* Globals */
54static struct nameidata rec_dir; 54static struct path rec_dir;
55static int rec_dir_init = 0; 55static int rec_dir_init = 0;
56 56
57static void 57static void
@@ -121,9 +121,9 @@ out_no_tfm:
121static void 121static void
122nfsd4_sync_rec_dir(void) 122nfsd4_sync_rec_dir(void)
123{ 123{
124 mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex); 124 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
125 nfsd_sync_dir(rec_dir.path.dentry); 125 nfsd_sync_dir(rec_dir.dentry);
126 mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex); 126 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
127} 127}
128 128
129int 129int
@@ -143,9 +143,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
143 nfs4_save_user(&uid, &gid); 143 nfs4_save_user(&uid, &gid);
144 144
145 /* lock the parent */ 145 /* lock the parent */
146 mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex); 146 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
147 147
148 dentry = lookup_one_len(dname, rec_dir.path.dentry, HEXDIR_LEN-1); 148 dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
149 if (IS_ERR(dentry)) { 149 if (IS_ERR(dentry)) {
150 status = PTR_ERR(dentry); 150 status = PTR_ERR(dentry);
151 goto out_unlock; 151 goto out_unlock;
@@ -155,15 +155,15 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
155 dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n"); 155 dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
156 goto out_put; 156 goto out_put;
157 } 157 }
158 status = mnt_want_write(rec_dir.path.mnt); 158 status = mnt_want_write(rec_dir.mnt);
159 if (status) 159 if (status)
160 goto out_put; 160 goto out_put;
161 status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU); 161 status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
162 mnt_drop_write(rec_dir.path.mnt); 162 mnt_drop_write(rec_dir.mnt);
163out_put: 163out_put:
164 dput(dentry); 164 dput(dentry);
165out_unlock: 165out_unlock:
166 mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex); 166 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
167 if (status == 0) { 167 if (status == 0) {
168 clp->cl_firststate = 1; 168 clp->cl_firststate = 1;
169 nfsd4_sync_rec_dir(); 169 nfsd4_sync_rec_dir();
@@ -226,7 +226,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
226 226
227 nfs4_save_user(&uid, &gid); 227 nfs4_save_user(&uid, &gid);
228 228
229 filp = dentry_open(dget(dir), mntget(rec_dir.path.mnt), O_RDONLY); 229 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
230 status = PTR_ERR(filp); 230 status = PTR_ERR(filp);
231 if (IS_ERR(filp)) 231 if (IS_ERR(filp))
232 goto out; 232 goto out;
@@ -291,9 +291,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
291 291
292 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 292 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
293 293
294 mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex); 294 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
295 dentry = lookup_one_len(name, rec_dir.path.dentry, namlen); 295 dentry = lookup_one_len(name, rec_dir.dentry, namlen);
296 mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex); 296 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
297 if (IS_ERR(dentry)) { 297 if (IS_ERR(dentry)) {
298 status = PTR_ERR(dentry); 298 status = PTR_ERR(dentry);
299 return status; 299 return status;
@@ -302,7 +302,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
302 if (!dentry->d_inode) 302 if (!dentry->d_inode)
303 goto out; 303 goto out;
304 304
305 status = nfsd4_clear_clid_dir(rec_dir.path.dentry, dentry); 305 status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
306out: 306out:
307 dput(dentry); 307 dput(dentry);
308 return status; 308 return status;
@@ -318,7 +318,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
318 if (!rec_dir_init || !clp->cl_firststate) 318 if (!rec_dir_init || !clp->cl_firststate)
319 return; 319 return;
320 320
321 status = mnt_want_write(rec_dir.path.mnt); 321 status = mnt_want_write(rec_dir.mnt);
322 if (status) 322 if (status)
323 goto out; 323 goto out;
324 clp->cl_firststate = 0; 324 clp->cl_firststate = 0;
@@ -327,7 +327,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
327 nfs4_reset_user(uid, gid); 327 nfs4_reset_user(uid, gid);
328 if (status == 0) 328 if (status == 0)
329 nfsd4_sync_rec_dir(); 329 nfsd4_sync_rec_dir();
330 mnt_drop_write(rec_dir.path.mnt); 330 mnt_drop_write(rec_dir.mnt);
331out: 331out:
332 if (status) 332 if (status)
333 printk("NFSD: Failed to remove expired client state directory" 333 printk("NFSD: Failed to remove expired client state directory"
@@ -357,17 +357,17 @@ nfsd4_recdir_purge_old(void) {
357 357
358 if (!rec_dir_init) 358 if (!rec_dir_init)
359 return; 359 return;
360 status = mnt_want_write(rec_dir.path.mnt); 360 status = mnt_want_write(rec_dir.mnt);
361 if (status) 361 if (status)
362 goto out; 362 goto out;
363 status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old); 363 status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
364 if (status == 0) 364 if (status == 0)
365 nfsd4_sync_rec_dir(); 365 nfsd4_sync_rec_dir();
366 mnt_drop_write(rec_dir.path.mnt); 366 mnt_drop_write(rec_dir.mnt);
367out: 367out:
368 if (status) 368 if (status)
369 printk("nfsd4: failed to purge old clients from recovery" 369 printk("nfsd4: failed to purge old clients from recovery"
370 " directory %s\n", rec_dir.path.dentry->d_name.name); 370 " directory %s\n", rec_dir.dentry->d_name.name);
371} 371}
372 372
373static int 373static int
@@ -387,10 +387,10 @@ int
387nfsd4_recdir_load(void) { 387nfsd4_recdir_load(void) {
388 int status; 388 int status;
389 389
390 status = nfsd4_list_rec_dir(rec_dir.path.dentry, load_recdir); 390 status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
391 if (status) 391 if (status)
392 printk("nfsd4: failed loading clients from recovery" 392 printk("nfsd4: failed loading clients from recovery"
393 " directory %s\n", rec_dir.path.dentry->d_name.name); 393 " directory %s\n", rec_dir.dentry->d_name.name);
394 return status; 394 return status;
395} 395}
396 396
@@ -412,7 +412,7 @@ nfsd4_init_recdir(char *rec_dirname)
412 412
413 nfs4_save_user(&uid, &gid); 413 nfs4_save_user(&uid, &gid);
414 414
415 status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, 415 status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
416 &rec_dir); 416 &rec_dir);
417 if (status) 417 if (status)
418 printk("NFSD: unable to find recovery directory %s\n", 418 printk("NFSD: unable to find recovery directory %s\n",
@@ -429,5 +429,5 @@ nfsd4_shutdown_recdir(void)
429 if (!rec_dir_init) 429 if (!rec_dir_init)
430 return; 430 return;
431 rec_dir_init = 0; 431 rec_dir_init = 0;
432 path_put(&rec_dir.path); 432 path_put(&rec_dir);
433} 433}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0cc7ff5d5ab5..b0bebc552a11 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3284,17 +3284,17 @@ int
3284nfs4_reset_recoverydir(char *recdir) 3284nfs4_reset_recoverydir(char *recdir)
3285{ 3285{
3286 int status; 3286 int status;
3287 struct nameidata nd; 3287 struct path path;
3288 3288
3289 status = path_lookup(recdir, LOOKUP_FOLLOW, &nd); 3289 status = kern_path(recdir, LOOKUP_FOLLOW, &path);
3290 if (status) 3290 if (status)
3291 return status; 3291 return status;
3292 status = -ENOTDIR; 3292 status = -ENOTDIR;
3293 if (S_ISDIR(nd.path.dentry->d_inode->i_mode)) { 3293 if (S_ISDIR(path.dentry->d_inode->i_mode)) {
3294 nfs4_set_recdir(recdir); 3294 nfs4_set_recdir(recdir);
3295 status = 0; 3295 status = 0;
3296 } 3296 }
3297 path_put(&nd.path); 3297 path_put(&path);
3298 return status; 3298 return status;
3299} 3299}
3300 3300
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 97543df58242..e3f9783fdcf7 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -341,7 +341,7 @@ static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
341 341
342static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size) 342static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
343{ 343{
344 struct nameidata nd; 344 struct path path;
345 char *fo_path; 345 char *fo_path;
346 int error; 346 int error;
347 347
@@ -356,13 +356,13 @@ static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
356 if (qword_get(&buf, fo_path, size) < 0) 356 if (qword_get(&buf, fo_path, size) < 0)
357 return -EINVAL; 357 return -EINVAL;
358 358
359 error = path_lookup(fo_path, 0, &nd); 359 error = kern_path(fo_path, 0, &path);
360 if (error) 360 if (error)
361 return error; 361 return error;
362 362
363 error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb); 363 error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
364 364
365 path_put(&nd.path); 365 path_put(&path);
366 return error; 366 return error;
367} 367}
368 368
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 9609eb51d727..0bc56f6d9276 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1818,6 +1818,115 @@ out:
1818} 1818}
1819 1819
1820/* 1820/*
1821 * We do this buffering because we must not call back into the file
1822 * system's ->lookup() method from the filldir callback. That may well
1823 * deadlock a number of file systems.
1824 *
1825 * This is based heavily on the implementation of same in XFS.
1826 */
1827struct buffered_dirent {
1828 u64 ino;
1829 loff_t offset;
1830 int namlen;
1831 unsigned int d_type;
1832 char name[];
1833};
1834
1835struct readdir_data {
1836 char *dirent;
1837 size_t used;
1838 int full;
1839};
1840
1841static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
1842 loff_t offset, u64 ino, unsigned int d_type)
1843{
1844 struct readdir_data *buf = __buf;
1845 struct buffered_dirent *de = (void *)(buf->dirent + buf->used);
1846 unsigned int reclen;
1847
1848 reclen = ALIGN(sizeof(struct buffered_dirent) + namlen, sizeof(u64));
1849 if (buf->used + reclen > PAGE_SIZE) {
1850 buf->full = 1;
1851 return -EINVAL;
1852 }
1853
1854 de->namlen = namlen;
1855 de->offset = offset;
1856 de->ino = ino;
1857 de->d_type = d_type;
1858 memcpy(de->name, name, namlen);
1859 buf->used += reclen;
1860
1861 return 0;
1862}
1863
1864static int nfsd_buffered_readdir(struct file *file, filldir_t func,
1865 struct readdir_cd *cdp, loff_t *offsetp)
1866{
1867 struct readdir_data buf;
1868 struct buffered_dirent *de;
1869 int host_err;
1870 int size;
1871 loff_t offset;
1872
1873 buf.dirent = (void *)__get_free_page(GFP_KERNEL);
1874 if (!buf.dirent)
1875 return -ENOMEM;
1876
1877 offset = *offsetp;
1878 cdp->err = nfserr_eof; /* will be cleared on successful read */
1879
1880 while (1) {
1881 unsigned int reclen;
1882
1883 buf.used = 0;
1884 buf.full = 0;
1885
1886 host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf);
1887 if (buf.full)
1888 host_err = 0;
1889
1890 if (host_err < 0)
1891 break;
1892
1893 size = buf.used;
1894
1895 if (!size)
1896 break;
1897
1898 de = (struct buffered_dirent *)buf.dirent;
1899 while (size > 0) {
1900 offset = de->offset;
1901
1902 if (func(cdp, de->name, de->namlen, de->offset,
1903 de->ino, de->d_type))
1904 goto done;
1905
1906 if (cdp->err != nfs_ok)
1907 goto done;
1908
1909 reclen = ALIGN(sizeof(*de) + de->namlen,
1910 sizeof(u64));
1911 size -= reclen;
1912 de = (struct buffered_dirent *)((char *)de + reclen);
1913 }
1914 offset = vfs_llseek(file, 0, SEEK_CUR);
1915 if (!buf.full)
1916 break;
1917 }
1918
1919 done:
1920 free_page((unsigned long)(buf.dirent));
1921
1922 if (host_err)
1923 return nfserrno(host_err);
1924
1925 *offsetp = offset;
1926 return cdp->err;
1927}
1928
1929/*
1821 * Read entries from a directory. 1930 * Read entries from a directory.
1822 * The NFSv3/4 verifier we ignore for now. 1931 * The NFSv3/4 verifier we ignore for now.
1823 */ 1932 */
@@ -1826,7 +1935,6 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
1826 struct readdir_cd *cdp, filldir_t func) 1935 struct readdir_cd *cdp, filldir_t func)
1827{ 1936{
1828 __be32 err; 1937 __be32 err;
1829 int host_err;
1830 struct file *file; 1938 struct file *file;
1831 loff_t offset = *offsetp; 1939 loff_t offset = *offsetp;
1832 1940
@@ -1840,21 +1948,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
1840 goto out_close; 1948 goto out_close;
1841 } 1949 }
1842 1950
1843 /* 1951 err = nfsd_buffered_readdir(file, func, cdp, offsetp);
1844 * Read the directory entries. This silly loop is necessary because
1845 * readdir() is not guaranteed to fill up the entire buffer, but
1846 * may choose to do less.
1847 */
1848
1849 do {
1850 cdp->err = nfserr_eof; /* will be cleared on successful read */
1851 host_err = vfs_readdir(file, func, cdp);
1852 } while (host_err >=0 && cdp->err == nfs_ok);
1853 if (host_err)
1854 err = nfserrno(host_err);
1855 else
1856 err = cdp->err;
1857 *offsetp = vfs_llseek(file, 0, 1);
1858 1952
1859 if (err == nfserr_eof || err == nfserr_toosmall) 1953 if (err == nfserr_eof || err == nfserr_toosmall)
1860 err = nfs_ok; /* can still be found in ->err */ 1954 err = nfs_ok; /* can still be found in ->err */