]> bbs.cooldavid.org Git - net-next-2.6.git/blob - fs/9p/vfs_inode.c
9p: Define and implement TLINK for 9P2000.L
[net-next-2.6.git] / fs / 9p / vfs_inode.c
1 /*
2  *  linux/fs/9p/vfs_inode.c
3  *
4  * This file contains vfs inode ops for the 9P2000 protocol.
5  *
6  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
7  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License version 2
11  *  as published by the Free Software Foundation.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to:
20  *  Free Software Foundation
21  *  51 Franklin Street, Fifth Floor
22  *  Boston, MA  02111-1301  USA
23  *
24  */
25
26 #include <linux/module.h>
27 #include <linux/errno.h>
28 #include <linux/fs.h>
29 #include <linux/file.h>
30 #include <linux/pagemap.h>
31 #include <linux/stat.h>
32 #include <linux/string.h>
33 #include <linux/inet.h>
34 #include <linux/namei.h>
35 #include <linux/idr.h>
36 #include <linux/sched.h>
37 #include <linux/slab.h>
38 #include <net/9p/9p.h>
39 #include <net/9p/client.h>
40
41 #include "v9fs.h"
42 #include "v9fs_vfs.h"
43 #include "fid.h"
44 #include "cache.h"
45
46 static const struct inode_operations v9fs_dir_inode_operations;
47 static const struct inode_operations v9fs_dir_inode_operations_dotu;
48 static const struct inode_operations v9fs_dir_inode_operations_dotl;
49 static const struct inode_operations v9fs_file_inode_operations;
50 static const struct inode_operations v9fs_file_inode_operations_dotl;
51 static const struct inode_operations v9fs_symlink_inode_operations;
52 static const struct inode_operations v9fs_symlink_inode_operations_dotl;
53
54 /**
55  * unixmode2p9mode - convert unix mode bits to plan 9
56  * @v9ses: v9fs session information
57  * @mode: mode to convert
58  *
59  */
60
61 static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
62 {
63         int res;
64         res = mode & 0777;
65         if (S_ISDIR(mode))
66                 res |= P9_DMDIR;
67         if (v9fs_proto_dotu(v9ses)) {
68                 if (S_ISLNK(mode))
69                         res |= P9_DMSYMLINK;
70                 if (v9ses->nodev == 0) {
71                         if (S_ISSOCK(mode))
72                                 res |= P9_DMSOCKET;
73                         if (S_ISFIFO(mode))
74                                 res |= P9_DMNAMEDPIPE;
75                         if (S_ISBLK(mode))
76                                 res |= P9_DMDEVICE;
77                         if (S_ISCHR(mode))
78                                 res |= P9_DMDEVICE;
79                 }
80
81                 if ((mode & S_ISUID) == S_ISUID)
82                         res |= P9_DMSETUID;
83                 if ((mode & S_ISGID) == S_ISGID)
84                         res |= P9_DMSETGID;
85                 if ((mode & S_ISVTX) == S_ISVTX)
86                         res |= P9_DMSETVTX;
87                 if ((mode & P9_DMLINK))
88                         res |= P9_DMLINK;
89         }
90
91         return res;
92 }
93
94 /**
95  * p9mode2unixmode- convert plan9 mode bits to unix mode bits
96  * @v9ses: v9fs session information
97  * @mode: mode to convert
98  *
99  */
100
101 static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
102 {
103         int res;
104
105         res = mode & 0777;
106
107         if ((mode & P9_DMDIR) == P9_DMDIR)
108                 res |= S_IFDIR;
109         else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
110                 res |= S_IFLNK;
111         else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
112                  && (v9ses->nodev == 0))
113                 res |= S_IFSOCK;
114         else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
115                  && (v9ses->nodev == 0))
116                 res |= S_IFIFO;
117         else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
118                  && (v9ses->nodev == 0))
119                 res |= S_IFBLK;
120         else
121                 res |= S_IFREG;
122
123         if (v9fs_proto_dotu(v9ses)) {
124                 if ((mode & P9_DMSETUID) == P9_DMSETUID)
125                         res |= S_ISUID;
126
127                 if ((mode & P9_DMSETGID) == P9_DMSETGID)
128                         res |= S_ISGID;
129
130                 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
131                         res |= S_ISVTX;
132         }
133
134         return res;
135 }
136
137 /**
138  * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
139  * @uflags: flags to convert
140  * @extended: if .u extensions are active
141  */
142
143 int v9fs_uflags2omode(int uflags, int extended)
144 {
145         int ret;
146
147         ret = 0;
148         switch (uflags&3) {
149         default:
150         case O_RDONLY:
151                 ret = P9_OREAD;
152                 break;
153
154         case O_WRONLY:
155                 ret = P9_OWRITE;
156                 break;
157
158         case O_RDWR:
159                 ret = P9_ORDWR;
160                 break;
161         }
162
163         if (uflags & O_TRUNC)
164                 ret |= P9_OTRUNC;
165
166         if (extended) {
167                 if (uflags & O_EXCL)
168                         ret |= P9_OEXCL;
169
170                 if (uflags & O_APPEND)
171                         ret |= P9_OAPPEND;
172         }
173
174         return ret;
175 }
176
177 /**
178  * v9fs_blank_wstat - helper function to setup a 9P stat structure
179  * @wstat: structure to initialize
180  *
181  */
182
183 void
184 v9fs_blank_wstat(struct p9_wstat *wstat)
185 {
186         wstat->type = ~0;
187         wstat->dev = ~0;
188         wstat->qid.type = ~0;
189         wstat->qid.version = ~0;
190         *((long long *)&wstat->qid.path) = ~0;
191         wstat->mode = ~0;
192         wstat->atime = ~0;
193         wstat->mtime = ~0;
194         wstat->length = ~0;
195         wstat->name = NULL;
196         wstat->uid = NULL;
197         wstat->gid = NULL;
198         wstat->muid = NULL;
199         wstat->n_uid = ~0;
200         wstat->n_gid = ~0;
201         wstat->n_muid = ~0;
202         wstat->extension = NULL;
203 }
204
205 #ifdef CONFIG_9P_FSCACHE
206 /**
207  * v9fs_alloc_inode - helper function to allocate an inode
208  * This callback is executed before setting up the inode so that we
209  * can associate a vcookie with each inode.
210  *
211  */
212
213 struct inode *v9fs_alloc_inode(struct super_block *sb)
214 {
215         struct v9fs_cookie *vcookie;
216         vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
217                                                          GFP_KERNEL);
218         if (!vcookie)
219                 return NULL;
220
221         vcookie->fscache = NULL;
222         vcookie->qid = NULL;
223         spin_lock_init(&vcookie->lock);
224         return &vcookie->inode;
225 }
226
227 /**
228  * v9fs_destroy_inode - destroy an inode
229  *
230  */
231
232 void v9fs_destroy_inode(struct inode *inode)
233 {
234         kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
235 }
236 #endif
237
238 /**
239  * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a
240  * new file system object. This checks the S_ISGID to determine the owning
241  * group of the new file system object.
242  */
243
244 static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
245 {
246         BUG_ON(dir_inode == NULL);
247
248         if (dir_inode->i_mode & S_ISGID) {
249                 /* set_gid bit is set.*/
250                 return dir_inode->i_gid;
251         }
252         return current_fsgid();
253 }
254
255 /**
256  * v9fs_dentry_from_dir_inode - helper function to get the dentry from
257  * dir inode.
258  *
259  */
260
261 struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
262 {
263         struct dentry *dentry;
264
265         spin_lock(&dcache_lock);
266         /* Directory should have only one entry. */
267         BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
268         dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
269         spin_unlock(&dcache_lock);
270         return dentry;
271 }
272
273 /**
274  * v9fs_get_inode - helper function to setup an inode
275  * @sb: superblock
276  * @mode: mode to setup inode with
277  *
278  */
279
280 struct inode *v9fs_get_inode(struct super_block *sb, int mode)
281 {
282         int err;
283         struct inode *inode;
284         struct v9fs_session_info *v9ses = sb->s_fs_info;
285
286         P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
287
288         inode = new_inode(sb);
289         if (!inode) {
290                 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
291                 return ERR_PTR(-ENOMEM);
292         }
293
294         inode_init_owner(inode, NULL, mode);
295         inode->i_blocks = 0;
296         inode->i_rdev = 0;
297         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
298         inode->i_mapping->a_ops = &v9fs_addr_operations;
299
300         switch (mode & S_IFMT) {
301         case S_IFIFO:
302         case S_IFBLK:
303         case S_IFCHR:
304         case S_IFSOCK:
305                 if (!v9fs_proto_dotu(v9ses)) {
306                         P9_DPRINTK(P9_DEBUG_ERROR,
307                                    "special files without extended mode\n");
308                         err = -EINVAL;
309                         goto error;
310                 }
311                 init_special_inode(inode, inode->i_mode, inode->i_rdev);
312                 break;
313         case S_IFREG:
314                 if (v9fs_proto_dotl(v9ses)) {
315                         inode->i_op = &v9fs_file_inode_operations_dotl;
316                         inode->i_fop = &v9fs_file_operations_dotl;
317                 } else {
318                         inode->i_op = &v9fs_file_inode_operations;
319                         inode->i_fop = &v9fs_file_operations;
320                 }
321
322                 break;
323
324         case S_IFLNK:
325                 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
326                         P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with "
327                                                 "legacy protocol.\n");
328                         err = -EINVAL;
329                         goto error;
330                 }
331
332                 if (v9fs_proto_dotl(v9ses))
333                         inode->i_op = &v9fs_symlink_inode_operations_dotl;
334                 else
335                         inode->i_op = &v9fs_symlink_inode_operations;
336
337                 break;
338         case S_IFDIR:
339                 inc_nlink(inode);
340                 if (v9fs_proto_dotl(v9ses))
341                         inode->i_op = &v9fs_dir_inode_operations_dotl;
342                 else if (v9fs_proto_dotu(v9ses))
343                         inode->i_op = &v9fs_dir_inode_operations_dotu;
344                 else
345                         inode->i_op = &v9fs_dir_inode_operations;
346
347                 if (v9fs_proto_dotl(v9ses))
348                         inode->i_fop = &v9fs_dir_operations_dotl;
349                 else
350                         inode->i_fop = &v9fs_dir_operations;
351
352                 break;
353         default:
354                 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
355                            mode, mode & S_IFMT);
356                 err = -EINVAL;
357                 goto error;
358         }
359
360         return inode;
361
362 error:
363         iput(inode);
364         return ERR_PTR(err);
365 }
366
367 /*
368 static struct v9fs_fid*
369 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
370 {
371         int err;
372         int nfid;
373         struct v9fs_fid *ret;
374         struct v9fs_fcall *fcall;
375
376         nfid = v9fs_get_idpool(&v9ses->fidpool);
377         if (nfid < 0) {
378                 eprintk(KERN_WARNING, "no free fids available\n");
379                 return ERR_PTR(-ENOSPC);
380         }
381
382         err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
383                 &fcall);
384
385         if (err < 0) {
386                 if (fcall && fcall->id == RWALK)
387                         goto clunk_fid;
388
389                 PRINT_FCALL_ERROR("walk error", fcall);
390                 v9fs_put_idpool(nfid, &v9ses->fidpool);
391                 goto error;
392         }
393
394         kfree(fcall);
395         fcall = NULL;
396         ret = v9fs_fid_create(v9ses, nfid);
397         if (!ret) {
398                 err = -ENOMEM;
399                 goto clunk_fid;
400         }
401
402         err = v9fs_fid_insert(ret, dentry);
403         if (err < 0) {
404                 v9fs_fid_destroy(ret);
405                 goto clunk_fid;
406         }
407
408         return ret;
409
410 clunk_fid:
411         v9fs_t_clunk(v9ses, nfid);
412
413 error:
414         kfree(fcall);
415         return ERR_PTR(err);
416 }
417 */
418
419
420 /**
421  * v9fs_clear_inode - release an inode
422  * @inode: inode to release
423  *
424  */
425 void v9fs_clear_inode(struct inode *inode)
426 {
427         filemap_fdatawrite(inode->i_mapping);
428
429 #ifdef CONFIG_9P_FSCACHE
430         v9fs_cache_inode_put_cookie(inode);
431 #endif
432 }
433
434 static struct inode *
435 v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid,
436         struct super_block *sb)
437 {
438         int err, umode;
439         struct inode *ret = NULL;
440         struct p9_wstat *st;
441
442         st = p9_client_stat(fid);
443         if (IS_ERR(st))
444                 return ERR_CAST(st);
445
446         umode = p9mode2unixmode(v9ses, st->mode);
447         ret = v9fs_get_inode(sb, umode);
448         if (IS_ERR(ret)) {
449                 err = PTR_ERR(ret);
450                 goto error;
451         }
452
453         v9fs_stat2inode(st, ret, sb);
454         ret->i_ino = v9fs_qid2ino(&st->qid);
455
456 #ifdef CONFIG_9P_FSCACHE
457         v9fs_vcookie_set_qid(ret, &st->qid);
458         v9fs_cache_inode_get_cookie(ret);
459 #endif
460         p9stat_free(st);
461         kfree(st);
462         return ret;
463 error:
464         p9stat_free(st);
465         kfree(st);
466         return ERR_PTR(err);
467 }
468
469 static struct inode *
470 v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
471         struct super_block *sb)
472 {
473         struct inode *ret = NULL;
474         int err;
475         struct p9_stat_dotl *st;
476
477         st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
478         if (IS_ERR(st))
479                 return ERR_CAST(st);
480
481         ret = v9fs_get_inode(sb, st->st_mode);
482         if (IS_ERR(ret)) {
483                 err = PTR_ERR(ret);
484                 goto error;
485         }
486
487         v9fs_stat2inode_dotl(st, ret);
488         ret->i_ino = v9fs_qid2ino(&st->qid);
489 #ifdef CONFIG_9P_FSCACHE
490         v9fs_vcookie_set_qid(ret, &st->qid);
491         v9fs_cache_inode_get_cookie(ret);
492 #endif
493         kfree(st);
494         return ret;
495 error:
496         kfree(st);
497         return ERR_PTR(err);
498 }
499
500 /**
501  * v9fs_inode_from_fid - Helper routine to populate an inode by
502  * issuing a attribute request
503  * @v9ses: session information
504  * @fid: fid to issue attribute request for
505  * @sb: superblock on which to create inode
506  *
507  */
508 static inline struct inode *
509 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
510                         struct super_block *sb)
511 {
512         if (v9fs_proto_dotl(v9ses))
513                 return v9fs_inode_dotl(v9ses, fid, sb);
514         else
515                 return v9fs_inode(v9ses, fid, sb);
516 }
517
518 /**
519  * v9fs_remove - helper function to remove files and directories
520  * @dir: directory inode that is being deleted
521  * @file:  dentry that is being deleted
522  * @rmdir: removing a directory
523  *
524  */
525
526 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
527 {
528         int retval;
529         struct inode *file_inode;
530         struct p9_fid *v9fid;
531
532         P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
533                 rmdir);
534
535         file_inode = file->d_inode;
536         v9fid = v9fs_fid_clone(file);
537         if (IS_ERR(v9fid))
538                 return PTR_ERR(v9fid);
539
540         retval = p9_client_remove(v9fid);
541         if (!retval)
542                 drop_nlink(file_inode);
543         return retval;
544 }
545
546 static int
547 v9fs_open_created(struct inode *inode, struct file *file)
548 {
549         return 0;
550 }
551
552
553 /**
554  * v9fs_create - Create a file
555  * @v9ses: session information
556  * @dir: directory that dentry is being created in
557  * @dentry:  dentry that is being created
558  * @extension: 9p2000.u extension string to support devices, etc.
559  * @perm: create permissions
560  * @mode: open mode
561  *
562  */
563 static struct p9_fid *
564 v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
565                 struct dentry *dentry, char *extension, u32 perm, u8 mode)
566 {
567         int err;
568         char *name;
569         struct p9_fid *dfid, *ofid, *fid;
570         struct inode *inode;
571
572         P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
573
574         err = 0;
575         ofid = NULL;
576         fid = NULL;
577         name = (char *) dentry->d_name.name;
578         dfid = v9fs_fid_lookup(dentry->d_parent);
579         if (IS_ERR(dfid)) {
580                 err = PTR_ERR(dfid);
581                 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
582                 return ERR_PTR(err);
583         }
584
585         /* clone a fid to use for creation */
586         ofid = p9_client_walk(dfid, 0, NULL, 1);
587         if (IS_ERR(ofid)) {
588                 err = PTR_ERR(ofid);
589                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
590                 return ERR_PTR(err);
591         }
592
593         err = p9_client_fcreate(ofid, name, perm, mode, extension);
594         if (err < 0) {
595                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
596                 goto error;
597         }
598
599         /* now walk from the parent so we can get unopened fid */
600         fid = p9_client_walk(dfid, 1, &name, 1);
601         if (IS_ERR(fid)) {
602                 err = PTR_ERR(fid);
603                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
604                 fid = NULL;
605                 goto error;
606         }
607
608         /* instantiate inode and assign the unopened fid to the dentry */
609         inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
610         if (IS_ERR(inode)) {
611                 err = PTR_ERR(inode);
612                 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
613                 goto error;
614         }
615
616         if (v9ses->cache)
617                 dentry->d_op = &v9fs_cached_dentry_operations;
618         else
619                 dentry->d_op = &v9fs_dentry_operations;
620
621         d_instantiate(dentry, inode);
622         err = v9fs_fid_add(dentry, fid);
623         if (err < 0)
624                 goto error;
625
626         return ofid;
627
628 error:
629         if (ofid)
630                 p9_client_clunk(ofid);
631
632         if (fid)
633                 p9_client_clunk(fid);
634
635         return ERR_PTR(err);
636 }
637
638 /**
639  * v9fs_vfs_create - VFS hook to create files
640  * @dir: directory inode that is being created
641  * @dentry:  dentry that is being deleted
642  * @mode: create permissions
643  * @nd: path information
644  *
645  */
646
647 static int
648 v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
649                 struct nameidata *nd)
650 {
651         int err;
652         u32 perm;
653         int flags;
654         struct v9fs_session_info *v9ses;
655         struct p9_fid *fid;
656         struct file *filp;
657
658         err = 0;
659         fid = NULL;
660         v9ses = v9fs_inode2v9ses(dir);
661         perm = unixmode2p9mode(v9ses, mode);
662         if (nd && nd->flags & LOOKUP_OPEN)
663                 flags = nd->intent.open.flags - 1;
664         else
665                 flags = O_RDWR;
666
667         fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
668                                 v9fs_uflags2omode(flags,
669                                                 v9fs_proto_dotu(v9ses)));
670         if (IS_ERR(fid)) {
671                 err = PTR_ERR(fid);
672                 fid = NULL;
673                 goto error;
674         }
675
676         /* if we are opening a file, assign the open fid to the file */
677         if (nd && nd->flags & LOOKUP_OPEN) {
678                 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
679                 if (IS_ERR(filp)) {
680                         err = PTR_ERR(filp);
681                         goto error;
682                 }
683
684                 filp->private_data = fid;
685         } else
686                 p9_client_clunk(fid);
687
688         return 0;
689
690 error:
691         if (fid)
692                 p9_client_clunk(fid);
693
694         return err;
695 }
696
697 /**
698  * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
699  * @dir:  inode that is being unlinked
700  * @dentry: dentry that is being unlinked
701  * @mode: mode for new directory
702  *
703  */
704
705 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
706 {
707         int err;
708         u32 perm;
709         struct v9fs_session_info *v9ses;
710         struct p9_fid *fid;
711
712         P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
713         err = 0;
714         v9ses = v9fs_inode2v9ses(dir);
715         perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
716         fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
717         if (IS_ERR(fid)) {
718                 err = PTR_ERR(fid);
719                 fid = NULL;
720         }
721
722         if (fid)
723                 p9_client_clunk(fid);
724
725         return err;
726 }
727
728 /**
729  * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
730  * @dir:  inode that is being walked from
731  * @dentry: dentry that is being walked to?
732  * @nameidata: path data
733  *
734  */
735
736 static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
737                                       struct nameidata *nameidata)
738 {
739         struct super_block *sb;
740         struct v9fs_session_info *v9ses;
741         struct p9_fid *dfid, *fid;
742         struct inode *inode;
743         char *name;
744         int result = 0;
745
746         P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
747                 dir, dentry->d_name.name, dentry, nameidata);
748
749         if (dentry->d_name.len > NAME_MAX)
750                 return ERR_PTR(-ENAMETOOLONG);
751
752         sb = dir->i_sb;
753         v9ses = v9fs_inode2v9ses(dir);
754         dfid = v9fs_fid_lookup(dentry->d_parent);
755         if (IS_ERR(dfid))
756                 return ERR_CAST(dfid);
757
758         name = (char *) dentry->d_name.name;
759         fid = p9_client_walk(dfid, 1, &name, 1);
760         if (IS_ERR(fid)) {
761                 result = PTR_ERR(fid);
762                 if (result == -ENOENT) {
763                         inode = NULL;
764                         goto inst_out;
765                 }
766
767                 return ERR_PTR(result);
768         }
769
770         inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
771         if (IS_ERR(inode)) {
772                 result = PTR_ERR(inode);
773                 inode = NULL;
774                 goto error;
775         }
776
777         result = v9fs_fid_add(dentry, fid);
778         if (result < 0)
779                 goto error;
780
781 inst_out:
782         if (v9ses->cache)
783                 dentry->d_op = &v9fs_cached_dentry_operations;
784         else
785                 dentry->d_op = &v9fs_dentry_operations;
786
787         d_add(dentry, inode);
788         return NULL;
789
790 error:
791         p9_client_clunk(fid);
792
793         return ERR_PTR(result);
794 }
795
796 /**
797  * v9fs_vfs_unlink - VFS unlink hook to delete an inode
798  * @i:  inode that is being unlinked
799  * @d: dentry that is being unlinked
800  *
801  */
802
803 static int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
804 {
805         return v9fs_remove(i, d, 0);
806 }
807
808 /**
809  * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
810  * @i:  inode that is being unlinked
811  * @d: dentry that is being unlinked
812  *
813  */
814
815 static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
816 {
817         return v9fs_remove(i, d, 1);
818 }
819
820 /**
821  * v9fs_vfs_rename - VFS hook to rename an inode
822  * @old_dir:  old dir inode
823  * @old_dentry: old dentry
824  * @new_dir: new dir inode
825  * @new_dentry: new dentry
826  *
827  */
828
829 static int
830 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
831                 struct inode *new_dir, struct dentry *new_dentry)
832 {
833         struct inode *old_inode;
834         struct v9fs_session_info *v9ses;
835         struct p9_fid *oldfid;
836         struct p9_fid *olddirfid;
837         struct p9_fid *newdirfid;
838         struct p9_wstat wstat;
839         int retval;
840
841         P9_DPRINTK(P9_DEBUG_VFS, "\n");
842         retval = 0;
843         old_inode = old_dentry->d_inode;
844         v9ses = v9fs_inode2v9ses(old_inode);
845         oldfid = v9fs_fid_lookup(old_dentry);
846         if (IS_ERR(oldfid))
847                 return PTR_ERR(oldfid);
848
849         olddirfid = v9fs_fid_clone(old_dentry->d_parent);
850         if (IS_ERR(olddirfid)) {
851                 retval = PTR_ERR(olddirfid);
852                 goto done;
853         }
854
855         newdirfid = v9fs_fid_clone(new_dentry->d_parent);
856         if (IS_ERR(newdirfid)) {
857                 retval = PTR_ERR(newdirfid);
858                 goto clunk_olddir;
859         }
860
861         if (v9fs_proto_dotl(v9ses)) {
862                 retval = p9_client_rename(oldfid, newdirfid,
863                                         (char *) new_dentry->d_name.name);
864                 if (retval != -ENOSYS)
865                         goto clunk_newdir;
866         }
867
868         /* 9P can only handle file rename in the same directory */
869         if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
870                 P9_DPRINTK(P9_DEBUG_ERROR,
871                                 "old dir and new dir are different\n");
872                 retval = -EXDEV;
873                 goto clunk_newdir;
874         }
875
876         v9fs_blank_wstat(&wstat);
877         wstat.muid = v9ses->uname;
878         wstat.name = (char *) new_dentry->d_name.name;
879         retval = p9_client_wstat(oldfid, &wstat);
880
881 clunk_newdir:
882         p9_client_clunk(newdirfid);
883
884 clunk_olddir:
885         p9_client_clunk(olddirfid);
886
887 done:
888         return retval;
889 }
890
891 /**
892  * v9fs_vfs_getattr - retrieve file metadata
893  * @mnt: mount information
894  * @dentry: file to get attributes on
895  * @stat: metadata structure to populate
896  *
897  */
898
899 static int
900 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
901                  struct kstat *stat)
902 {
903         int err;
904         struct v9fs_session_info *v9ses;
905         struct p9_fid *fid;
906         struct p9_wstat *st;
907
908         P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
909         err = -EPERM;
910         v9ses = v9fs_inode2v9ses(dentry->d_inode);
911         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
912                 return simple_getattr(mnt, dentry, stat);
913
914         fid = v9fs_fid_lookup(dentry);
915         if (IS_ERR(fid))
916                 return PTR_ERR(fid);
917
918         st = p9_client_stat(fid);
919         if (IS_ERR(st))
920                 return PTR_ERR(st);
921
922         v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
923                 generic_fillattr(dentry->d_inode, stat);
924
925         kfree(st);
926         return 0;
927 }
928
929 static int
930 v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
931                  struct kstat *stat)
932 {
933         int err;
934         struct v9fs_session_info *v9ses;
935         struct p9_fid *fid;
936         struct p9_stat_dotl *st;
937
938         P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
939         err = -EPERM;
940         v9ses = v9fs_inode2v9ses(dentry->d_inode);
941         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
942                 return simple_getattr(mnt, dentry, stat);
943
944         fid = v9fs_fid_lookup(dentry);
945         if (IS_ERR(fid))
946                 return PTR_ERR(fid);
947
948         /* Ask for all the fields in stat structure. Server will return
949          * whatever it supports
950          */
951
952         st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
953         if (IS_ERR(st))
954                 return PTR_ERR(st);
955
956         v9fs_stat2inode_dotl(st, dentry->d_inode);
957         generic_fillattr(dentry->d_inode, stat);
958         /* Change block size to what the server returned */
959         stat->blksize = st->st_blksize;
960
961         kfree(st);
962         return 0;
963 }
964
965 /**
966  * v9fs_vfs_setattr - set file metadata
967  * @dentry: file whose metadata to set
968  * @iattr: metadata assignment structure
969  *
970  */
971
972 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
973 {
974         int retval;
975         struct v9fs_session_info *v9ses;
976         struct p9_fid *fid;
977         struct p9_wstat wstat;
978
979         P9_DPRINTK(P9_DEBUG_VFS, "\n");
980         retval = -EPERM;
981         v9ses = v9fs_inode2v9ses(dentry->d_inode);
982         fid = v9fs_fid_lookup(dentry);
983         if(IS_ERR(fid))
984                 return PTR_ERR(fid);
985
986         v9fs_blank_wstat(&wstat);
987         if (iattr->ia_valid & ATTR_MODE)
988                 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
989
990         if (iattr->ia_valid & ATTR_MTIME)
991                 wstat.mtime = iattr->ia_mtime.tv_sec;
992
993         if (iattr->ia_valid & ATTR_ATIME)
994                 wstat.atime = iattr->ia_atime.tv_sec;
995
996         if (iattr->ia_valid & ATTR_SIZE)
997                 wstat.length = iattr->ia_size;
998
999         if (v9fs_proto_dotu(v9ses)) {
1000                 if (iattr->ia_valid & ATTR_UID)
1001                         wstat.n_uid = iattr->ia_uid;
1002
1003                 if (iattr->ia_valid & ATTR_GID)
1004                         wstat.n_gid = iattr->ia_gid;
1005         }
1006
1007         retval = p9_client_wstat(fid, &wstat);
1008         if (retval >= 0)
1009                 retval = inode_setattr(dentry->d_inode, iattr);
1010
1011         return retval;
1012 }
1013
1014 /**
1015  * v9fs_vfs_setattr_dotl - set file metadata
1016  * @dentry: file whose metadata to set
1017  * @iattr: metadata assignment structure
1018  *
1019  */
1020
1021 static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
1022 {
1023         int retval;
1024         struct v9fs_session_info *v9ses;
1025         struct p9_fid *fid;
1026         struct p9_iattr_dotl p9attr;
1027
1028         P9_DPRINTK(P9_DEBUG_VFS, "\n");
1029
1030         retval = inode_change_ok(dentry->d_inode, iattr);
1031         if (retval)
1032                 return retval;
1033
1034         p9attr.valid = iattr->ia_valid;
1035         p9attr.mode = iattr->ia_mode;
1036         p9attr.uid = iattr->ia_uid;
1037         p9attr.gid = iattr->ia_gid;
1038         p9attr.size = iattr->ia_size;
1039         p9attr.atime_sec = iattr->ia_atime.tv_sec;
1040         p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
1041         p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
1042         p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
1043
1044         retval = -EPERM;
1045         v9ses = v9fs_inode2v9ses(dentry->d_inode);
1046         fid = v9fs_fid_lookup(dentry);
1047         if (IS_ERR(fid))
1048                 return PTR_ERR(fid);
1049
1050         retval = p9_client_setattr(fid, &p9attr);
1051         if (retval >= 0)
1052                 retval = inode_setattr(dentry->d_inode, iattr);
1053
1054         return retval;
1055 }
1056
1057 /**
1058  * v9fs_stat2inode - populate an inode structure with mistat info
1059  * @stat: Plan 9 metadata (mistat) structure
1060  * @inode: inode to populate
1061  * @sb: superblock of filesystem
1062  *
1063  */
1064
1065 void
1066 v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1067         struct super_block *sb)
1068 {
1069         char ext[32];
1070         char tag_name[14];
1071         unsigned int i_nlink;
1072         struct v9fs_session_info *v9ses = sb->s_fs_info;
1073
1074         inode->i_nlink = 1;
1075
1076         inode->i_atime.tv_sec = stat->atime;
1077         inode->i_mtime.tv_sec = stat->mtime;
1078         inode->i_ctime.tv_sec = stat->mtime;
1079
1080         inode->i_uid = v9ses->dfltuid;
1081         inode->i_gid = v9ses->dfltgid;
1082
1083         if (v9fs_proto_dotu(v9ses)) {
1084                 inode->i_uid = stat->n_uid;
1085                 inode->i_gid = stat->n_gid;
1086         }
1087         if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1088                 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1089                         /*
1090                          * Hadlink support got added later to
1091                          * to the .u extension. So there can be
1092                          * server out there that doesn't support
1093                          * this even with .u extension. So check
1094                          * for non NULL stat->extension
1095                          */
1096                         strncpy(ext, stat->extension, sizeof(ext));
1097                         /* HARDLINKCOUNT %u */
1098                         sscanf(ext, "%13s %u", tag_name, &i_nlink);
1099                         if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1100                                 inode->i_nlink = i_nlink;
1101                 }
1102         }
1103         inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
1104         if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
1105                 char type = 0;
1106                 int major = -1;
1107                 int minor = -1;
1108
1109                 strncpy(ext, stat->extension, sizeof(ext));
1110                 sscanf(ext, "%c %u %u", &type, &major, &minor);
1111                 switch (type) {
1112                 case 'c':
1113                         inode->i_mode &= ~S_IFBLK;
1114                         inode->i_mode |= S_IFCHR;
1115                         break;
1116                 case 'b':
1117                         break;
1118                 default:
1119                         P9_DPRINTK(P9_DEBUG_ERROR,
1120                                 "Unknown special type %c %s\n", type,
1121                                 stat->extension);
1122                 };
1123                 inode->i_rdev = MKDEV(major, minor);
1124                 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1125         } else
1126                 inode->i_rdev = 0;
1127
1128         i_size_write(inode, stat->length);
1129
1130         /* not real number of blocks, but 512 byte ones ... */
1131         inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1132 }
1133
1134 /**
1135  * v9fs_stat2inode_dotl - populate an inode structure with stat info
1136  * @stat: stat structure
1137  * @inode: inode to populate
1138  * @sb: superblock of filesystem
1139  *
1140  */
1141
1142 void
1143 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
1144 {
1145
1146         if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
1147                 inode->i_atime.tv_sec = stat->st_atime_sec;
1148                 inode->i_atime.tv_nsec = stat->st_atime_nsec;
1149                 inode->i_mtime.tv_sec = stat->st_mtime_sec;
1150                 inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
1151                 inode->i_ctime.tv_sec = stat->st_ctime_sec;
1152                 inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
1153                 inode->i_uid = stat->st_uid;
1154                 inode->i_gid = stat->st_gid;
1155                 inode->i_nlink = stat->st_nlink;
1156                 inode->i_mode = stat->st_mode;
1157                 inode->i_rdev = new_decode_dev(stat->st_rdev);
1158
1159                 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode)))
1160                         init_special_inode(inode, inode->i_mode, inode->i_rdev);
1161
1162                 i_size_write(inode, stat->st_size);
1163                 inode->i_blocks = stat->st_blocks;
1164         } else {
1165                 if (stat->st_result_mask & P9_STATS_ATIME) {
1166                         inode->i_atime.tv_sec = stat->st_atime_sec;
1167                         inode->i_atime.tv_nsec = stat->st_atime_nsec;
1168                 }
1169                 if (stat->st_result_mask & P9_STATS_MTIME) {
1170                         inode->i_mtime.tv_sec = stat->st_mtime_sec;
1171                         inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
1172                 }
1173                 if (stat->st_result_mask & P9_STATS_CTIME) {
1174                         inode->i_ctime.tv_sec = stat->st_ctime_sec;
1175                         inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
1176                 }
1177                 if (stat->st_result_mask & P9_STATS_UID)
1178                         inode->i_uid = stat->st_uid;
1179                 if (stat->st_result_mask & P9_STATS_GID)
1180                         inode->i_gid = stat->st_gid;
1181                 if (stat->st_result_mask & P9_STATS_NLINK)
1182                         inode->i_nlink = stat->st_nlink;
1183                 if (stat->st_result_mask & P9_STATS_MODE) {
1184                         inode->i_mode = stat->st_mode;
1185                         if ((S_ISBLK(inode->i_mode)) ||
1186                                                 (S_ISCHR(inode->i_mode)))
1187                                 init_special_inode(inode, inode->i_mode,
1188                                                                 inode->i_rdev);
1189                 }
1190                 if (stat->st_result_mask & P9_STATS_RDEV)
1191                         inode->i_rdev = new_decode_dev(stat->st_rdev);
1192                 if (stat->st_result_mask & P9_STATS_SIZE)
1193                         i_size_write(inode, stat->st_size);
1194                 if (stat->st_result_mask & P9_STATS_BLOCKS)
1195                         inode->i_blocks = stat->st_blocks;
1196         }
1197         if (stat->st_result_mask & P9_STATS_GEN)
1198                         inode->i_generation = stat->st_gen;
1199
1200         /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
1201          * because the inode structure does not have fields for them.
1202          */
1203 }
1204
1205 /**
1206  * v9fs_qid2ino - convert qid into inode number
1207  * @qid: qid to hash
1208  *
1209  * BUG: potential for inode number collisions?
1210  */
1211
1212 ino_t v9fs_qid2ino(struct p9_qid *qid)
1213 {
1214         u64 path = qid->path + 2;
1215         ino_t i = 0;
1216
1217         if (sizeof(ino_t) == sizeof(path))
1218                 memcpy(&i, &path, sizeof(ino_t));
1219         else
1220                 i = (ino_t) (path ^ (path >> 32));
1221
1222         return i;
1223 }
1224
1225 /**
1226  * v9fs_readlink - read a symlink's location (internal version)
1227  * @dentry: dentry for symlink
1228  * @buffer: buffer to load symlink location into
1229  * @buflen: length of buffer
1230  *
1231  */
1232
1233 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1234 {
1235         int retval;
1236
1237         struct v9fs_session_info *v9ses;
1238         struct p9_fid *fid;
1239         struct p9_wstat *st;
1240
1241         P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1242         retval = -EPERM;
1243         v9ses = v9fs_inode2v9ses(dentry->d_inode);
1244         fid = v9fs_fid_lookup(dentry);
1245         if (IS_ERR(fid))
1246                 return PTR_ERR(fid);
1247
1248         if (!v9fs_proto_dotu(v9ses))
1249                 return -EBADF;
1250
1251         st = p9_client_stat(fid);
1252         if (IS_ERR(st))
1253                 return PTR_ERR(st);
1254
1255         if (!(st->mode & P9_DMSYMLINK)) {
1256                 retval = -EINVAL;
1257                 goto done;
1258         }
1259
1260         /* copy extension buffer into buffer */
1261         strncpy(buffer, st->extension, buflen);
1262
1263         P9_DPRINTK(P9_DEBUG_VFS,
1264                 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
1265
1266         retval = strnlen(buffer, buflen);
1267 done:
1268         kfree(st);
1269         return retval;
1270 }
1271
1272 /**
1273  * v9fs_vfs_follow_link - follow a symlink path
1274  * @dentry: dentry for symlink
1275  * @nd: nameidata
1276  *
1277  */
1278
1279 static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1280 {
1281         int len = 0;
1282         char *link = __getname();
1283
1284         P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
1285
1286         if (!link)
1287                 link = ERR_PTR(-ENOMEM);
1288         else {
1289                 len = v9fs_readlink(dentry, link, PATH_MAX);
1290
1291                 if (len < 0) {
1292                         __putname(link);
1293                         link = ERR_PTR(len);
1294                 } else
1295                         link[min(len, PATH_MAX-1)] = 0;
1296         }
1297         nd_set_link(nd, link);
1298
1299         return NULL;
1300 }
1301
1302 /**
1303  * v9fs_vfs_put_link - release a symlink path
1304  * @dentry: dentry for symlink
1305  * @nd: nameidata
1306  * @p: unused
1307  *
1308  */
1309
1310 static void
1311 v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1312 {
1313         char *s = nd_get_link(nd);
1314
1315         P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
1316                 IS_ERR(s) ? "<error>" : s);
1317         if (!IS_ERR(s))
1318                 __putname(s);
1319 }
1320
1321 /**
1322  * v9fs_vfs_mkspecial - create a special file
1323  * @dir: inode to create special file in
1324  * @dentry: dentry to create
1325  * @mode: mode to create special file
1326  * @extension: 9p2000.u format extension string representing special file
1327  *
1328  */
1329
1330 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1331         int mode, const char *extension)
1332 {
1333         u32 perm;
1334         struct v9fs_session_info *v9ses;
1335         struct p9_fid *fid;
1336
1337         v9ses = v9fs_inode2v9ses(dir);
1338         if (!v9fs_proto_dotu(v9ses)) {
1339                 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
1340                 return -EPERM;
1341         }
1342
1343         perm = unixmode2p9mode(v9ses, mode);
1344         fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1345                                                                 P9_OREAD);
1346         if (IS_ERR(fid))
1347                 return PTR_ERR(fid);
1348
1349         p9_client_clunk(fid);
1350         return 0;
1351 }
1352
1353 /**
1354  * v9fs_vfs_symlink - helper function to create symlinks
1355  * @dir: directory inode containing symlink
1356  * @dentry: dentry for symlink
1357  * @symname: symlink data
1358  *
1359  * See Also: 9P2000.u RFC for more information
1360  *
1361  */
1362
1363 static int
1364 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1365 {
1366         P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
1367                                         dentry->d_name.name, symname);
1368
1369         return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
1370 }
1371
1372 /**
1373  * v9fs_vfs_link - create a hardlink
1374  * @old_dentry: dentry for file to link to
1375  * @dir: inode destination for new link
1376  * @dentry: dentry for link
1377  *
1378  */
1379
1380 static int
1381 v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1382               struct dentry *dentry)
1383 {
1384         int retval;
1385         struct p9_fid *oldfid;
1386         char *name;
1387
1388         P9_DPRINTK(P9_DEBUG_VFS,
1389                 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
1390                 old_dentry->d_name.name);
1391
1392         oldfid = v9fs_fid_clone(old_dentry);
1393         if (IS_ERR(oldfid))
1394                 return PTR_ERR(oldfid);
1395
1396         name = __getname();
1397         if (unlikely(!name)) {
1398                 retval = -ENOMEM;
1399                 goto clunk_fid;
1400         }
1401
1402         sprintf(name, "%d\n", oldfid->fid);
1403         retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1404         __putname(name);
1405
1406 clunk_fid:
1407         p9_client_clunk(oldfid);
1408         return retval;
1409 }
1410
1411 /**
1412  * v9fs_vfs_link_dotl - create a hardlink for dotl
1413  * @old_dentry: dentry for file to link to
1414  * @dir: inode destination for new link
1415  * @dentry: dentry for link
1416  *
1417  */
1418
1419 static int
1420 v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
1421                 struct dentry *dentry)
1422 {
1423         int err;
1424         struct p9_fid *dfid, *oldfid;
1425         char *name;
1426         struct v9fs_session_info *v9ses;
1427         struct dentry *dir_dentry;
1428
1429         P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n",
1430                         dir->i_ino, old_dentry->d_name.name,
1431                         dentry->d_name.name);
1432
1433         v9ses = v9fs_inode2v9ses(dir);
1434         dir_dentry = v9fs_dentry_from_dir_inode(dir);
1435         dfid = v9fs_fid_lookup(dir_dentry);
1436         if (IS_ERR(dfid))
1437                 return PTR_ERR(dfid);
1438
1439         oldfid = v9fs_fid_lookup(old_dentry);
1440         if (IS_ERR(oldfid))
1441                 return PTR_ERR(oldfid);
1442
1443         name = (char *) dentry->d_name.name;
1444
1445         err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name);
1446
1447         if (err < 0) {
1448                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
1449                 return err;
1450         }
1451
1452         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1453                 /* Get the latest stat info from server. */
1454                 struct p9_fid *fid;
1455                 struct p9_stat_dotl *st;
1456
1457                 fid = v9fs_fid_lookup(old_dentry);
1458                 if (IS_ERR(fid))
1459                         return PTR_ERR(fid);
1460
1461                 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
1462                 if (IS_ERR(st))
1463                         return PTR_ERR(st);
1464
1465                 v9fs_stat2inode_dotl(st, old_dentry->d_inode);
1466
1467                 kfree(st);
1468         } else {
1469                 /* Caching disabled. No need to get upto date stat info.
1470                  * This dentry will be released immediately. So, just i_count++
1471                  */
1472                 atomic_inc(&old_dentry->d_inode->i_count);
1473         }
1474
1475         dentry->d_op = old_dentry->d_op;
1476         d_instantiate(dentry, old_dentry->d_inode);
1477
1478         return err;
1479 }
1480
1481 /**
1482  * v9fs_vfs_mknod - create a special file
1483  * @dir: inode destination for new link
1484  * @dentry: dentry for file
1485  * @mode: mode for creation
1486  * @rdev: device associated with special file
1487  *
1488  */
1489
1490 static int
1491 v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1492 {
1493         int retval;
1494         char *name;
1495
1496         P9_DPRINTK(P9_DEBUG_VFS,
1497                 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
1498                 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1499
1500         if (!new_valid_dev(rdev))
1501                 return -EINVAL;
1502
1503         name = __getname();
1504         if (!name)
1505                 return -ENOMEM;
1506         /* build extension */
1507         if (S_ISBLK(mode))
1508                 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1509         else if (S_ISCHR(mode))
1510                 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1511         else if (S_ISFIFO(mode))
1512                 *name = 0;
1513         else if (S_ISSOCK(mode))
1514                 *name = 0;
1515         else {
1516                 __putname(name);
1517                 return -EINVAL;
1518         }
1519
1520         retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
1521         __putname(name);
1522
1523         return retval;
1524 }
1525
1526 static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1527         .create = v9fs_vfs_create,
1528         .lookup = v9fs_vfs_lookup,
1529         .symlink = v9fs_vfs_symlink,
1530         .link = v9fs_vfs_link_dotl,
1531         .unlink = v9fs_vfs_unlink,
1532         .mkdir = v9fs_vfs_mkdir,
1533         .rmdir = v9fs_vfs_rmdir,
1534         .mknod = v9fs_vfs_mknod,
1535         .rename = v9fs_vfs_rename,
1536         .getattr = v9fs_vfs_getattr,
1537         .setattr = v9fs_vfs_setattr,
1538 };
1539
1540 static const struct inode_operations v9fs_dir_inode_operations_dotl = {
1541         .create = v9fs_vfs_create,
1542         .lookup = v9fs_vfs_lookup,
1543         .symlink = v9fs_vfs_symlink,
1544         .link = v9fs_vfs_link,
1545         .unlink = v9fs_vfs_unlink,
1546         .mkdir = v9fs_vfs_mkdir,
1547         .rmdir = v9fs_vfs_rmdir,
1548         .mknod = v9fs_vfs_mknod,
1549         .rename = v9fs_vfs_rename,
1550         .getattr = v9fs_vfs_getattr_dotl,
1551         .setattr = v9fs_vfs_setattr_dotl,
1552 };
1553
1554 static const struct inode_operations v9fs_dir_inode_operations = {
1555         .create = v9fs_vfs_create,
1556         .lookup = v9fs_vfs_lookup,
1557         .unlink = v9fs_vfs_unlink,
1558         .mkdir = v9fs_vfs_mkdir,
1559         .rmdir = v9fs_vfs_rmdir,
1560         .mknod = v9fs_vfs_mknod,
1561         .rename = v9fs_vfs_rename,
1562         .getattr = v9fs_vfs_getattr,
1563         .setattr = v9fs_vfs_setattr,
1564 };
1565
1566 static const struct inode_operations v9fs_file_inode_operations = {
1567         .getattr = v9fs_vfs_getattr,
1568         .setattr = v9fs_vfs_setattr,
1569 };
1570
1571 static const struct inode_operations v9fs_file_inode_operations_dotl = {
1572         .getattr = v9fs_vfs_getattr_dotl,
1573         .setattr = v9fs_vfs_setattr_dotl,
1574 };
1575
1576 static const struct inode_operations v9fs_symlink_inode_operations = {
1577         .readlink = generic_readlink,
1578         .follow_link = v9fs_vfs_follow_link,
1579         .put_link = v9fs_vfs_put_link,
1580         .getattr = v9fs_vfs_getattr,
1581         .setattr = v9fs_vfs_setattr,
1582 };
1583
1584 static const struct inode_operations v9fs_symlink_inode_operations_dotl = {
1585         .readlink = generic_readlink,
1586         .follow_link = v9fs_vfs_follow_link,
1587         .put_link = v9fs_vfs_put_link,
1588         .getattr = v9fs_vfs_getattr_dotl,
1589         .setattr = v9fs_vfs_setattr_dotl,
1590 };