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