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