Whamcloud - gitweb
Modified ChangeLog entry.
[fs/lustre-release.git] / lustre / kernel_patches / patches / nfs_export_kernel-2.4.20-hp.patch
1  fs/Makefile        |    3 
2  fs/file_table.c    |   11 ++
3  fs/inode.c         |   23 ++++-
4  fs/namei.c         |   12 ++
5  fs/nfsd/export.c   |    5 +
6  fs/nfsd/nfsfh.c    |   65 +++++++++++++-
7  fs/nfsd/vfs.c      |  240 ++++++++++++++++++++++++++++++++++++++++++++++++-----
8  include/linux/fs.h |   10 ++
9  kernel/ksyms.c     |    2 
10  9 files changed, 337 insertions(+), 34 deletions(-)
11
12 --- linux-2.4.20-hp4-pnnl13/fs/file_table.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300
13 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/file_table.c      2003-10-08 10:54:08.000000000 +0400
14 @@ -82,7 +82,8 @@ struct file * get_empty_filp(void)
15   * and call the open function (if any).  The caller must verify that
16   * inode->i_fop is not NULL.
17   */
18 -int init_private_file(struct file *filp, struct dentry *dentry, int mode)
19 +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
20 +                        struct lookup_intent *it)
21  {
22         memset(filp, 0, sizeof(*filp));
23         filp->f_mode   = mode;
24 @@ -90,12 +91,20 @@ int init_private_file(struct file *filp,
25         filp->f_dentry = dentry;
26         filp->f_uid    = current->fsuid;
27         filp->f_gid    = current->fsgid;
28 +       if (it)
29 +               filp->f_it = it;
30         filp->f_op     = dentry->d_inode->i_fop;
31         if (filp->f_op->open)
32                 return filp->f_op->open(dentry->d_inode, filp);
33         else
34                 return 0;
35  }
36 +EXPORT_SYMBOL(init_private_file_it);
37 +
38 +int init_private_file(struct file *filp, struct dentry *dentry, int mode)
39 +{
40 +       return init_private_file_it(filp, dentry, mode, NULL);
41 +}
42  
43  void fput(struct file * file)
44  {
45 --- linux-2.4.20-hp4-pnnl13/fs/inode.c~nfs_export_kernel-2.4.20-hp      2003-09-14 17:34:20.000000000 +0400
46 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/inode.c   2003-10-08 11:38:11.000000000 +0400
47 @@ -964,9 +964,10 @@ struct inode *igrab(struct inode *inode)
48         return inode;
49  }
50  
51 -struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
52 +struct inode *ifind(struct super_block *sb, unsigned long ino,
53 +                   struct list_head *head,
54 +                   find_inode_t find_actor, void *opaque)
55  {
56 -       struct list_head * head = inode_hashtable + hash(sb,ino);
57         struct inode * inode;
58  
59         spin_lock(&inode_lock);
60 @@ -979,6 +980,24 @@ struct inode *iget4_locked(struct super_
61         }
62         spin_unlock(&inode_lock);
63  
64 +       return NULL;
65 +}
66 +
67 +struct inode *ilookup4(struct super_block *sb, unsigned long ino,
68 +                      find_inode_t find_actor, void *opaque)
69 +{
70 +       struct list_head * head = inode_hashtable + hash(sb,ino);
71 +       return ifind(sb, ino, head, find_actor, opaque);
72 +}
73 +
74 +struct inode *iget4_locked(struct super_block *sb, unsigned long ino,
75 +                          find_inode_t find_actor, void *opaque)
76 +{
77 +       struct list_head * head = inode_hashtable + hash(sb,ino);
78 +       struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
79 +       if (inode)
80 +               return inode;
81 +
82         /*
83          * get_new_inode() will do the right thing, re-trying the search
84          * in case it had to block at any point.
85 --- linux-2.4.20-hp4-pnnl13/fs/Makefile~nfs_export_kernel-2.4.20-hp     2003-09-14 17:34:22.000000000 +0400
86 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/Makefile  2003-10-08 10:54:37.000000000 +0400
87 @@ -7,7 +7,8 @@
88  
89  O_TARGET := fs.o
90  
91 -export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o
92 +export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \
93 +               namei.o file_table.o
94  mod-subdirs := nls xfs
95  
96  obj-y :=       open.o read_write.o devices.o file_table.o buffer.o \
97 --- linux-2.4.20-hp4-pnnl13/fs/namei.c~nfs_export_kernel-2.4.20-hp      2003-09-14 17:34:20.000000000 +0400
98 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/namei.c   2003-10-08 10:54:08.000000000 +0400
99 @@ -22,6 +22,7 @@
100  #include <linux/dnotify.h>
101  #include <linux/smp_lock.h>
102  #include <linux/personality.h>
103 +#include <linux/module.h>
104  
105  #include <asm/namei.h>
106  #include <asm/uaccess.h>
107 @@ -100,6 +101,7 @@ void intent_release(struct lookup_intent
108                 it->it_op_release(it);
109  
110  }
111 +EXPORT_SYMBOL(intent_release);
112  
113  /* In order to reduce some races, while at the same time doing additional
114   * checking and hopefully speeding things up, we copy filenames to the
115 @@ -917,7 +919,8 @@ struct dentry * lookup_hash(struct qstr 
116  
117  
118  /* SMP-safe */
119 -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
120 +struct dentry * lookup_one_len_it(const char * name, struct dentry * base,
121 +                                 int len, struct lookup_intent *it)
122  {
123         unsigned long hash;
124         struct qstr this;
125 @@ -937,11 +940,16 @@ struct dentry * lookup_one_len(const cha
126         }
127         this.hash = end_name_hash(hash);
128  
129 -       return lookup_hash_it(&this, base, NULL);
130 +       return lookup_hash_it(&this, base, it);
131  access:
132         return ERR_PTR(-EACCES);
133  }
134  
135 +struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
136 +{
137 +       return lookup_one_len_it(name, base, len, NULL);
138 +}
139 +
140  /*
141   *     namei()
142   *
143 --- linux-2.4.20-hp4-pnnl13/fs/nfsd/export.c~nfs_export_kernel-2.4.20-hp        2002-11-29 02:53:15.000000000 +0300
144 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/export.c     2003-10-08 10:54:08.000000000 +0400
145 @@ -222,6 +222,11 @@ exp_export(struct nfsctl_export *nxp)
146         inode = nd.dentry->d_inode;
147         dev = inode->i_dev;
148         ino = inode->i_ino;
149 +       if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
150 +           !(nxp->ex_flags & NFSEXP_FSID)) {
151 +               nxp->ex_dev = inode->i_sb->s_dev;
152 +               nxp->ex_flags |= NFSEXP_FSID;
153 +       }
154         err = -EINVAL;
155  
156         exp = exp_get(clp, dev, ino);
157 --- linux-2.4.20-hp4-pnnl13/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300
158 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/nfsfh.c      2003-10-08 10:54:08.000000000 +0400
159 @@ -36,6 +36,13 @@ struct nfsd_getdents_callback {
160         int sequence;           /* sequence counter */
161  };
162  
163 +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
164 +{
165 +       if (inode->i_op->lookup_it)
166 +               return inode->i_op->lookup_it(inode, dentry, NULL, 0);
167 +       return inode->i_op->lookup(inode, dentry);
168 +}
169 +
170  /*
171   * A rather strange filldir function to capture
172   * the name matching the specified inode number.
173 @@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry *
174         int error;
175         struct file file;
176         struct nfsd_getdents_callback buffer;
177 +       struct lookup_intent it;
178 +       struct file *filp = NULL;
179  
180         error = -ENOTDIR;
181         if (!dir || !S_ISDIR(dir->i_mode))
182 @@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry *
183         /*
184          * Open the directory ...
185          */
186 -       error = init_private_file(&file, dentry, FMODE_READ);
187 -       if (error)
188 +       if (dentry->d_op && dentry->d_op->d_revalidate_it) {
189 +               if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
190 +                   (dentry->d_parent == dentry) ) {
191 +                       it.it_op_release = NULL;
192 +                       /*
193 +                        * XXX Temporary Hack: Simulate init_private_file without
194 +                        * f_op->open for disconnected dentry as we don't have
195 +                        * actual dentry->d_name to revalidate in revalidate_it()
196 +                        */
197 +                       filp = &file;
198 +                       memset(filp, 0, sizeof(*filp));
199 +                       filp->f_mode   = FMODE_READ;
200 +                       atomic_set(&filp->f_count, 1);
201 +                       filp->f_dentry = dentry;
202 +                       filp->f_uid = current->fsuid;
203 +                       filp->f_gid = current->fsgid;
204 +                       filp->f_op = dentry->d_inode->i_fop;
205 +                       error = 0;
206 +               } else {
207 +                       intent_init(&it, IT_OPEN, FMODE_READ);
208 +                       error = revalidate_it(dentry, &it);
209 +                       if (error)
210 +                               goto out;
211 +                       error = init_private_file_it(&file, dentry, FMODE_READ, &it);
212 +               }
213 +       } else {
214 +               error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
215 +       }
216 +       if (error)
217                 goto out;
218 +
219         error = -EINVAL;
220         if (!file.f_op->readdir)
221                 goto out_close;
222 @@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry *
223         }
224  
225  out_close:
226 -       if (file.f_op->release)
227 +       if (file.f_op->release && !filp)
228                 file.f_op->release(dir, &file);
229  out:
230 +       if (dentry->d_op && dentry->d_op->d_revalidate_it &&
231 +           it.it_op_release && !filp)
232 +               intent_release(&it);
233         return error;
234  }
235  
236 @@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de
237          * it is well connected.  But nobody returns different dentrys do they?
238          */
239         down(&child->d_inode->i_sem);
240 -       pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
241 +       pdentry = lookup_it(child->d_inode, tdentry);
242         up(&child->d_inode->i_sem);
243         d_drop(tdentry); /* we never want ".." hashed */
244         if (!pdentry && tdentry->d_inode == NULL) {
245 @@ -306,6 +349,8 @@ struct dentry *nfsd_findparent(struct de
246                                 igrab(tdentry->d_inode);
247                                 pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
248                         }
249 +                       if (child->d_op && child->d_op->d_revalidate_it)
250 +                               pdentry->d_op = child->d_op;
251                 }
252                 if (pdentry == NULL)
253                         pdentry = ERR_PTR(-ENOMEM);
254 @@ -463,6 +508,8 @@ find_fh_dentry(struct super_block *sb, _
255                 struct dentry *pdentry;
256                 struct inode *parent;
257  
258 +               if (result->d_op && result->d_op->d_revalidate_it)
259 +                       dentry->d_op = result->d_op;
260                 pdentry = nfsd_findparent(dentry);
261                 err = PTR_ERR(pdentry);
262                 if (IS_ERR(pdentry))
263 @@ -662,6 +709,10 @@ fh_verify(struct svc_rqst *rqstp, struct
264  
265         inode = dentry->d_inode;
266  
267 +       /* cache coherency for non-device filesystems */
268 +       if (inode->i_op && inode->i_op->revalidate_it)
269 +               inode->i_op->revalidate_it(dentry, NULL);
270 +
271         /* Type check. The correct error return for type mismatches
272          * does not seem to be generally agreed upon. SunOS seems to
273          * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
274 @@ -900,8 +952,9 @@ out_negative:
275                 dentry->d_parent->d_name.name, dentry->d_name.name);
276         goto out;
277  out_uptodate:
278 -       printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
279 -               dentry->d_parent->d_name.name, dentry->d_name.name);
280 +       if (!dentry->d_parent->d_inode->i_op->mkdir_raw)
281 +               printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
282 +                     dentry->d_parent->d_name.name, dentry->d_name.name);
283         goto out;
284  }
285  
286 --- linux-2.4.20-hp4-pnnl13/fs/nfsd/vfs.c~nfs_export_kernel-2.4.20-hp   2002-11-29 02:53:15.000000000 +0300
287 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/vfs.c        2003-10-08 10:54:08.000000000 +0400
288 @@ -77,6 +77,130 @@ struct raparms {
289  static struct raparms *                raparml;
290  static struct raparms *                raparm_cache;
291  
292 +static int link_raw(struct dentry *dold, struct dentry *ddir,
293 +                   struct dentry *dnew)
294 +{
295 +       int err;
296 +
297 +       struct nameidata old_nd = { .dentry = dold };
298 +       struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
299 +       struct inode_operations *op = nd.dentry->d_inode->i_op;
300 +       err = op->link_raw(&old_nd, &nd);
301 +       igrab(dold->d_inode);
302 +       d_instantiate(dnew, dold->d_inode);
303 +       if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
304 +               dold->d_inode->i_op->revalidate_it(dnew, NULL);
305 +
306 +       return err;
307 +}
308 +
309 +static int unlink_raw(struct dentry *dentry, char *fname, int flen,
310 +                     struct dentry *rdentry)
311 +{
312 +       int err;
313 +       struct qstr last = { .name = fname, .len = flen };
314 +       struct nameidata nd = { .dentry = dentry, .last = last };
315 +       struct inode_operations *op = nd.dentry->d_inode->i_op;
316 +       err = op->unlink_raw(&nd);
317 +       if (!err)
318 +               d_delete(rdentry);
319 +
320 +       return err;
321 +}
322 +
323 +static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
324 +                    struct dentry *rdentry)
325 +{
326 +       int err;
327 +       struct qstr last = { .name = fname, .len = flen };
328 +       struct nameidata nd = { .dentry = dentry, .last = last };
329 +       struct inode_operations *op = nd.dentry->d_inode->i_op;
330 +       err = op->rmdir_raw(&nd);
331 +       if (!err) {
332 +               rdentry->d_inode->i_flags |= S_DEAD;
333 +               d_delete(rdentry);
334 +       }
335 +
336 +       return err;
337 +}
338 +
339 +static int symlink_raw(struct dentry *dentry, char *fname, int flen,
340 +                      char *path)
341 +{
342 +       int err;
343 +       struct qstr last = { .name = fname, .len = flen };
344 +       struct nameidata nd = { .dentry = dentry, .last = last };
345 +       struct inode_operations *op = nd.dentry->d_inode->i_op;
346 +       err = op->symlink_raw(&nd, path);
347 +
348 +       return err;
349 +}
350 +
351 +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
352 +{
353 +       int err;
354 +       struct qstr last = { .name = fname, .len = flen };
355 +       struct nameidata nd = { .dentry = dentry, .last = last };
356 +       struct inode_operations *op = nd.dentry->d_inode->i_op;
357 +       err = op->mkdir_raw(&nd, mode);
358 +
359 +       return err;
360 +}
361 +
362 +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
363 +                    dev_t dev)
364 +{
365 +       int err;
366 +       struct qstr last = { .name = fname, .len = flen };
367 +       struct nameidata nd = { .dentry = dentry, .last = last };
368 +       struct inode_operations *op = nd.dentry->d_inode->i_op;
369 +       err = op->mknod_raw(&nd, mode, dev);
370 +
371 +       return err;
372 +}
373 +
374 +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
375 +                     struct dentry *odentry, struct dentry *ndentry)
376 +{
377 +       int err;
378 +
379 +       struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
380 +       struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
381 +       struct inode_operations *op = old_nd.dentry->d_inode->i_op;
382 +       err = op->rename_raw(&old_nd, &new_nd);
383 +       d_move(odentry, ndentry);
384 +
385 +       return err;
386 +}
387 +
388 +#ifndef O_OWNER_OVERRIDE
389 +#define O_OWNER_OVERRIDE 0200000000
390 +#endif
391 +static int setattr_raw(struct inode *inode, struct iattr *iap)
392 +{
393 +       int err;
394 +
395 +       iap->ia_valid |= ATTR_RAW;
396 +       err = inode->i_op->setattr_raw(inode, iap);
397 +
398 +       return err;
399 +}
400 +
401 +int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
402 +{
403 +       int err = 0;
404 +
405 +       if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
406 +               if (!dentry->d_op->d_revalidate_it(dentry, 0, it) &&
407 +                       !d_invalidate(dentry)) {
408 +                       err = -EINVAL;
409 +                       return err;
410 +               }
411 +       }
412 +
413 +       return err;
414 +}
415 +
416  /*
417   * Look up one component of a pathname.
418   * N.B. After this call _both_ fhp and resfh need an fh_put
419 @@ -300,7 +422,12 @@ nfsd_setattr(struct svc_rqst *rqstp, str
420         }
421         err = nfserr_notsync;
422         if (!check_guard || guardtime == inode->i_ctime) {
423 -               err = notify_change(dentry, iap);
424 +               if (dentry->d_inode->i_op &&dentry->d_inode->i_op->setattr_raw){
425 +                       if (accmode & MAY_OWNER_OVERRIDE)
426 +                               iap->ia_valid & O_OWNER_OVERRIDE;
427 +                       err = setattr_raw(dentry->d_inode, iap);
428 +               } else
429 +                       err = notify_change(dentry, iap);
430                 err = nfserrno(err);
431         }
432         if (size_change) {
433 @@ -427,6 +552,7 @@ nfsd_open(struct svc_rqst *rqstp, struct
434  {
435         struct dentry   *dentry;
436         struct inode    *inode;
437 +       struct lookup_intent it;
438         int             err;
439  
440         /* If we get here, then the client has already done an "open", and (hopefully)
441 @@ -473,6 +599,15 @@ nfsd_open(struct svc_rqst *rqstp, struct
442                 filp->f_mode  = FMODE_READ;
443         }
444  
445 +       intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode |
446 +                   O_OWNER_OVERRIDE);
447 +
448 +       err = revalidate_it(dentry, &it);
449 +       if (err)
450 +               goto out_nfserr;
451 +
452 +       filp->f_it = &it;
453 +
454         err = 0;
455         if (filp->f_op && filp->f_op->open) {
456                 err = filp->f_op->open(inode, filp);
457 @@ -487,6 +621,9 @@ nfsd_open(struct svc_rqst *rqstp, struct
458                 }
459         }
460  out_nfserr:
461 +       if (it.it_op_release)
462 +               intent_release(&it);
463 +
464         if (err)
465                 err = nfserrno(err);
466  out:
467 @@ -818,7 +956,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
468  {
469         struct dentry   *dentry, *dchild;
470         struct inode    *dirp;
471 -       int             err;
472 +       int             err, error = -EOPNOTSUPP;
473  
474         err = nfserr_perm;
475         if (!flen)
476 @@ -834,20 +972,47 @@ nfsd_create(struct svc_rqst *rqstp, stru
477         dentry = fhp->fh_dentry;
478         dirp = dentry->d_inode;
479  
480 +       switch (type) {
481 +       case S_IFDIR:
482 +               if (dirp->i_op->mkdir_raw)
483 +                       error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
484 +               break;
485 +       case S_IFCHR:
486 +       case S_IFBLK:
487 +       case S_IFIFO:
488 +       case S_IFSOCK:
489 +       case S_IFREG:
490 +               if (dirp->i_op->mknod_raw) {
491 +                       if (type == S_IFREG)
492 +                               rdev = 0;
493 +                       error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev);
494 +               }
495 +               break;
496 +       default:
497 +               printk("nfsd: bad file type %o in nfsd_create\n", type);
498 +       }
499 +       if (error && error != -EOPNOTSUPP) {
500 +               err = error;
501 +               goto out_nfserr;
502 +       }
503 +
504         err = nfserr_notdir;
505 -       if(!dirp->i_op || !dirp->i_op->lookup)
506 +       if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
507                 goto out;
508         /*
509          * Check whether the response file handle has been verified yet.
510          * If it has, the parent directory should already be locked.
511          */
512 -       if (!resfhp->fh_dentry) {
513 -               /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
514 -               fh_lock(fhp);
515 +       if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
516 +               /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
517 +                * and nfsd_proc_create in case of lustre */
518 +               if (!resfhp->fh_dentry)
519 +                       fh_lock(fhp);
520                 dchild = lookup_one_len(fname, dentry, flen);
521                 err = PTR_ERR(dchild);
522                 if (IS_ERR(dchild))
523                         goto out_nfserr;
524 +               resfhp->fh_dentry = NULL;
525                 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
526                 if (err)
527                         goto out;
528 @@ -868,10 +1030,12 @@ nfsd_create(struct svc_rqst *rqstp, stru
529          * Make sure the child dentry is still negative ...
530          */
531         err = nfserr_exist;
532 -       if (dchild->d_inode) {
533 -               dprintk("nfsd_create: dentry %s/%s not negative!\n",
534 -                       dentry->d_name.name, dchild->d_name.name);
535 -               goto out; 
536 +       if (error == -EOPNOTSUPP) {
537 +               if (dchild->d_inode) {
538 +                       dprintk("nfsd_create: dentry %s/%s not negative!\n",
539 +                               dentry->d_name.name, dchild->d_name.name);
540 +                       goto out;
541 +               }
542         }
543  
544         if (!(iap->ia_valid & ATTR_MODE))
545 @@ -884,16 +1048,19 @@ nfsd_create(struct svc_rqst *rqstp, stru
546         err = nfserr_perm;
547         switch (type) {
548         case S_IFREG:
549 -               err = vfs_create(dirp, dchild, iap->ia_mode);
550 +               if (error == -EOPNOTSUPP)
551 +                       err = vfs_create(dirp, dchild, iap->ia_mode);
552                 break;
553         case S_IFDIR:
554 -               err = vfs_mkdir(dirp, dchild, iap->ia_mode);
555 +               if (error == -EOPNOTSUPP)
556 +                       err = vfs_mkdir(dirp, dchild, iap->ia_mode);
557                 break;
558         case S_IFCHR:
559         case S_IFBLK:
560         case S_IFIFO:
561         case S_IFSOCK:
562 -               err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
563 +               if (error == -EOPNOTSUPP)
564 +                       err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
565                 break;
566         default:
567                 printk("nfsd: bad file type %o in nfsd_create\n", type);
568 @@ -962,7 +1129,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
569         /* Get all the sanity checks out of the way before
570          * we lock the parent. */
571         err = nfserr_notdir;
572 -       if(!dirp->i_op || !dirp->i_op->lookup)
573 +       if (dirp->i_op->mknod_raw) {
574 +               err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
575 +               if (err && err != -EOPNOTSUPP)
576 +                       goto out_nfserr;
577 +       }
578 +
579 +       if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
580                 goto out;
581         fh_lock(fhp);
582  
583 @@ -1013,6 +1186,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
584                 case NFS3_CREATE_GUARDED:
585                         err = nfserr_exist;
586                 }
587 +               if (dirp->i_op->mknod_raw)
588 +                       err = 0;
589                 goto out;
590         }
591  
592 @@ -1119,7 +1294,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
593                                 struct iattr *iap)
594  {
595         struct dentry   *dentry, *dnew;
596 -       int             err, cerr;
597 +       int             err, cerr, error = -EOPNOTSUPP;
598  
599         err = nfserr_noent;
600         if (!flen || !plen)
601 @@ -1133,12 +1308,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str
602                 goto out;
603         fh_lock(fhp);
604         dentry = fhp->fh_dentry;
605 +
606 +       if (dentry->d_inode->i_op->symlink_raw)
607 +               error = symlink_raw(dentry, fname, flen, path);
608 +
609         dnew = lookup_one_len(fname, dentry, flen);
610         err = PTR_ERR(dnew);
611         if (IS_ERR(dnew))
612                 goto out_nfserr;
613  
614 -       err = vfs_symlink(dentry->d_inode, dnew, path);
615 +       err = error;
616 +       if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
617 +               err = vfs_symlink(dentry->d_inode, dnew, path);
618         if (!err) {
619                 if (EX_ISSYNC(fhp->fh_export))
620                         nfsd_sync_dir(dentry);
621 @@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
622                                 iap->ia_valid |= ATTR_CTIME;
623                                 iap->ia_mode = (iap->ia_mode&S_IALLUGO)
624                                         | S_IFLNK;
625 -                               err = notify_change(dnew, iap);
626 +                               if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
627 +                                       err = setattr_raw(dnew->d_inode, iap);
628 +                               else
629 +                                       err = notify_change(dnew, iap);
630                                 if (!err && EX_ISSYNC(fhp->fh_export))
631                                         write_inode_now(dentry->d_inode, 1);
632                        }
633 @@ -1206,7 +1390,10 @@ nfsd_link(struct svc_rqst *rqstp, struct
634         dold = tfhp->fh_dentry;
635         dest = dold->d_inode;
636  
637 -       err = vfs_link(dold, dirp, dnew);
638 +       if (dirp->i_op->link_raw)
639 +               err = link_raw(dold, ddir, dnew);
640 +       else
641 +               err = vfs_link(dold, dirp, dnew);
642         if (!err) {
643                 if (EX_ISSYNC(ffhp->fh_export)) {
644                         nfsd_sync_dir(ddir);
645 @@ -1291,7 +1478,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru
646                         err = nfserr_perm;
647         } else
648  #endif
649 -       err = vfs_rename(fdir, odentry, tdir, ndentry);
650 +       if (fdir->i_op->rename_raw)
651 +               err = rename_raw(fdentry, tdentry, odentry, ndentry);
652 +       else
653 +               err = vfs_rename(fdir, odentry, tdir, ndentry);
654         if (!err && EX_ISSYNC(tfhp->fh_export)) {
655                 nfsd_sync_dir(tdentry);
656                 nfsd_sync_dir(fdentry);
657 @@ -1312,7 +1502,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
658         fill_post_wcc(tfhp);
659         double_up(&tdir->i_sem, &fdir->i_sem);
660         ffhp->fh_locked = tfhp->fh_locked = 0;
661 -       
662 +
663  out:
664         return err;
665  }
666 @@ -1358,9 +1548,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
667                         err = nfserr_perm;
668                 } else
669  #endif
670 -               err = vfs_unlink(dirp, rdentry);
671 +               if (dirp->i_op->unlink_raw)
672 +                       err = unlink_raw(dentry, fname, flen, rdentry);
673 +               else
674 +                       err = vfs_unlink(dirp, rdentry);
675         } else { /* It's RMDIR */
676 -               err = vfs_rmdir(dirp, rdentry);
677 +               if (dirp->i_op->rmdir_raw)
678 +                       err = rmdir_raw(dentry, fname, flen, rdentry);
679 +               else
680 +                       err = vfs_rmdir(dirp, rdentry);
681         }
682  
683         dput(rdentry);
684 --- linux-2.4.20-hp4-pnnl13/include/linux/fs.h~nfs_export_kernel-2.4.20-hp      2003-09-14 17:34:24.000000000 +0400
685 +++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs.h   2003-10-08 11:39:07.000000000 +0400
686 @@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena
687  #define FS_SINGLE      8 /* Filesystem that can have only one superblock */
688  #define FS_NOMOUNT     16 /* Never mount from userland */
689  #define FS_LITTER      32 /* Keeps the tree in dcache */
690 +#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
691 +                           * exporting non device filesystems. */
692  #define FS_ODD_RENAME  32768   /* Temporary stuff; will go away as soon
693                                   * as nfs_rename() will be cleaned up
694                                   */
695 @@ -1116,6 +1119,9 @@ extern int open_namei_it(const char *fil
696                          struct nameidata *nd, struct lookup_intent *it);
697  extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
698                             int flags, struct lookup_intent *it);
699 +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
700 +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
701 +                               struct lookup_intent *it);
702  extern int filp_close(struct file *, fl_owner_t id);
703  extern char * getname(const char *);
704  
705 @@ -1386,6 +1392,8 @@ extern void path_release(struct nameidat
706  extern int follow_down(struct vfsmount **, struct dentry **);
707  extern int follow_up(struct vfsmount **, struct dentry **);
708  extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
709 +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
710 +                                        struct lookup_intent *);
711  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
712  #define user_path_walk(name,nd)         __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
713  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
714 @@ -1403,6 +1411,8 @@ typedef int (*find_inode_t)(struct inode
715  
716  extern struct inode * iget4_locked(struct super_block *, unsigned long,
717                                    find_inode_t, void *);
718 +extern struct inode * ilookup4(struct super_block *, unsigned long,
719 +                              find_inode_t, void *);
720  
721  static inline struct inode *iget4(struct super_block *sb, unsigned long ino,
722                                   find_inode_t find_actor, void *opaque)
723 --- linux-2.4.20-hp4-pnnl13/kernel/ksyms.c~nfs_export_kernel-2.4.20-hp  2003-09-14 17:34:22.000000000 +0400
724 +++ linux-2.4.20-hp4-pnnl13-alexey/kernel/ksyms.c       2003-10-08 11:39:42.000000000 +0400
725 @@ -169,6 +169,7 @@ EXPORT_SYMBOL(fget);
726  EXPORT_SYMBOL(igrab);
727  EXPORT_SYMBOL(iunique);
728  EXPORT_SYMBOL(iget4_locked);
729 +EXPORT_SYMBOL(ilookup4);
730  EXPORT_SYMBOL(unlock_new_inode);
731  EXPORT_SYMBOL(iput);
732  EXPORT_SYMBOL(inode_init_once);
733 @@ -181,6 +182,7 @@ EXPORT_SYMBOL(path_walk);
734  EXPORT_SYMBOL(path_release);
735  EXPORT_SYMBOL(__user_walk);
736  EXPORT_SYMBOL(lookup_one_len);
737 +EXPORT_SYMBOL(lookup_one_len_it);
738  EXPORT_SYMBOL(lookup_hash);
739  EXPORT_SYMBOL(sys_close);
740  EXPORT_SYMBOL(dcache_lock);