Merge branches 'upstream-fixes' and 'magicmouse' into for-linus
[pandora-kernel.git] / fs / 9p / vfs_inode_dotl.c
1 /*
2  *  linux/fs/9p/vfs_inode_dotl.c
3  *
4  * This file contains vfs inode ops for the 9P2000.L 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 int
51 v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
52                     dev_t rdev);
53
54 /**
55  * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a
56  * new file system object. This checks the S_ISGID to determine the owning
57  * group of the new file system object.
58  */
59
60 static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
61 {
62         BUG_ON(dir_inode == NULL);
63
64         if (dir_inode->i_mode & S_ISGID) {
65                 /* set_gid bit is set.*/
66                 return dir_inode->i_gid;
67         }
68         return current_fsgid();
69 }
70
71 /**
72  * v9fs_dentry_from_dir_inode - helper function to get the dentry from
73  * dir inode.
74  *
75  */
76
77 static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
78 {
79         struct dentry *dentry;
80
81         spin_lock(&inode->i_lock);
82         /* Directory should have only one entry. */
83         BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
84         dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
85         spin_unlock(&inode->i_lock);
86         return dentry;
87 }
88
89 static int v9fs_test_inode_dotl(struct inode *inode, void *data)
90 {
91         struct v9fs_inode *v9inode = V9FS_I(inode);
92         struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
93
94         /* don't match inode of different type */
95         if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
96                 return 0;
97
98         if (inode->i_generation != st->st_gen)
99                 return 0;
100
101         /* compare qid details */
102         if (memcmp(&v9inode->qid.version,
103                    &st->qid.version, sizeof(v9inode->qid.version)))
104                 return 0;
105
106         if (v9inode->qid.type != st->qid.type)
107                 return 0;
108         return 1;
109 }
110
111 /* Always get a new inode */
112 static int v9fs_test_new_inode_dotl(struct inode *inode, void *data)
113 {
114         return 0;
115 }
116
117 static int v9fs_set_inode_dotl(struct inode *inode,  void *data)
118 {
119         struct v9fs_inode *v9inode = V9FS_I(inode);
120         struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
121
122         memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
123         inode->i_generation = st->st_gen;
124         return 0;
125 }
126
127 static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
128                                         struct p9_qid *qid,
129                                         struct p9_fid *fid,
130                                         struct p9_stat_dotl *st,
131                                         int new)
132 {
133         int retval;
134         unsigned long i_ino;
135         struct inode *inode;
136         struct v9fs_session_info *v9ses = sb->s_fs_info;
137         int (*test)(struct inode *, void *);
138
139         if (new)
140                 test = v9fs_test_new_inode_dotl;
141         else
142                 test = v9fs_test_inode_dotl;
143
144         i_ino = v9fs_qid2ino(qid);
145         inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
146         if (!inode)
147                 return ERR_PTR(-ENOMEM);
148         if (!(inode->i_state & I_NEW))
149                 return inode;
150         /*
151          * initialize the inode with the stat info
152          * FIXME!! we may need support for stale inodes
153          * later.
154          */
155         inode->i_ino = i_ino;
156         retval = v9fs_init_inode(v9ses, inode, st->st_mode);
157         if (retval)
158                 goto error;
159
160         v9fs_stat2inode_dotl(st, inode);
161 #ifdef CONFIG_9P_FSCACHE
162         v9fs_cache_inode_get_cookie(inode);
163 #endif
164         retval = v9fs_get_acl(inode, fid);
165         if (retval)
166                 goto error;
167
168         unlock_new_inode(inode);
169         return inode;
170 error:
171         unlock_new_inode(inode);
172         iput(inode);
173         return ERR_PTR(retval);
174
175 }
176
177 struct inode *
178 v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
179                          struct super_block *sb, int new)
180 {
181         struct p9_stat_dotl *st;
182         struct inode *inode = NULL;
183
184         st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN);
185         if (IS_ERR(st))
186                 return ERR_CAST(st);
187
188         inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new);
189         kfree(st);
190         return inode;
191 }
192
193 /**
194  * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
195  * @dir: directory inode that is being created
196  * @dentry:  dentry that is being deleted
197  * @mode: create permissions
198  * @nd: path information
199  *
200  */
201
202 static int
203 v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
204                 struct nameidata *nd)
205 {
206         int err = 0;
207         gid_t gid;
208         int flags;
209         umode_t mode;
210         char *name = NULL;
211         struct file *filp;
212         struct p9_qid qid;
213         struct inode *inode;
214         struct p9_fid *fid = NULL;
215         struct v9fs_inode *v9inode;
216         struct p9_fid *dfid, *ofid, *inode_fid;
217         struct v9fs_session_info *v9ses;
218         struct posix_acl *pacl = NULL, *dacl = NULL;
219
220         v9ses = v9fs_inode2v9ses(dir);
221         if (nd)
222                 flags = nd->intent.open.flags;
223         else {
224                 /*
225                  * create call without LOOKUP_OPEN is due
226                  * to mknod of regular files. So use mknod
227                  * operation.
228                  */
229                 return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
230         }
231
232         name = (char *) dentry->d_name.name;
233         P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x "
234                         "mode:0x%x\n", name, flags, omode);
235
236         dfid = v9fs_fid_lookup(dentry->d_parent);
237         if (IS_ERR(dfid)) {
238                 err = PTR_ERR(dfid);
239                 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
240                 return err;
241         }
242
243         /* clone a fid to use for creation */
244         ofid = p9_client_walk(dfid, 0, NULL, 1);
245         if (IS_ERR(ofid)) {
246                 err = PTR_ERR(ofid);
247                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
248                 return err;
249         }
250
251         gid = v9fs_get_fsgid_for_create(dir);
252
253         mode = omode;
254         /* Update mode based on ACL value */
255         err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
256         if (err) {
257                 P9_DPRINTK(P9_DEBUG_VFS,
258                            "Failed to get acl values in creat %d\n", err);
259                 goto error;
260         }
261         err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
262         if (err < 0) {
263                 P9_DPRINTK(P9_DEBUG_VFS,
264                                 "p9_client_open_dotl failed in creat %d\n",
265                                 err);
266                 goto error;
267         }
268         v9fs_invalidate_inode_attr(dir);
269
270         /* instantiate inode and assign the unopened fid to the dentry */
271         fid = p9_client_walk(dfid, 1, &name, 1);
272         if (IS_ERR(fid)) {
273                 err = PTR_ERR(fid);
274                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
275                 fid = NULL;
276                 goto error;
277         }
278         inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
279         if (IS_ERR(inode)) {
280                 err = PTR_ERR(inode);
281                 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
282                 goto error;
283         }
284         d_instantiate(dentry, inode);
285         err = v9fs_fid_add(dentry, fid);
286         if (err < 0)
287                 goto error;
288
289         /* Now set the ACL based on the default value */
290         v9fs_set_create_acl(dentry, &dacl, &pacl);
291
292         v9inode = V9FS_I(inode);
293         mutex_lock(&v9inode->v_mutex);
294         if (v9ses->cache && !v9inode->writeback_fid &&
295             ((flags & O_ACCMODE) != O_RDONLY)) {
296                 /*
297                  * clone a fid and add it to writeback_fid
298                  * we do it during open time instead of
299                  * page dirty time via write_begin/page_mkwrite
300                  * because we want write after unlink usecase
301                  * to work.
302                  */
303                 inode_fid = v9fs_writeback_fid(dentry);
304                 if (IS_ERR(inode_fid)) {
305                         err = PTR_ERR(inode_fid);
306                         mutex_unlock(&v9inode->v_mutex);
307                         goto err_clunk_old_fid;
308                 }
309                 v9inode->writeback_fid = (void *) inode_fid;
310         }
311         mutex_unlock(&v9inode->v_mutex);
312         /* Since we are opening a file, assign the open fid to the file */
313         filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
314         if (IS_ERR(filp)) {
315                 err = PTR_ERR(filp);
316                 goto err_clunk_old_fid;
317         }
318         filp->private_data = ofid;
319 #ifdef CONFIG_9P_FSCACHE
320         if (v9ses->cache)
321                 v9fs_cache_inode_set_cookie(inode, filp);
322 #endif
323         return 0;
324
325 error:
326         if (fid)
327                 p9_client_clunk(fid);
328 err_clunk_old_fid:
329         if (ofid)
330                 p9_client_clunk(ofid);
331         v9fs_set_create_acl(NULL, &dacl, &pacl);
332         return err;
333 }
334
335 /**
336  * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory
337  * @dir:  inode that is being unlinked
338  * @dentry: dentry that is being unlinked
339  * @mode: mode for new directory
340  *
341  */
342
343 static int v9fs_vfs_mkdir_dotl(struct inode *dir,
344                                struct dentry *dentry, int omode)
345 {
346         int err;
347         struct v9fs_session_info *v9ses;
348         struct p9_fid *fid = NULL, *dfid = NULL;
349         gid_t gid;
350         char *name;
351         umode_t mode;
352         struct inode *inode;
353         struct p9_qid qid;
354         struct dentry *dir_dentry;
355         struct posix_acl *dacl = NULL, *pacl = NULL;
356
357         P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
358         err = 0;
359         v9ses = v9fs_inode2v9ses(dir);
360
361         omode |= S_IFDIR;
362         if (dir->i_mode & S_ISGID)
363                 omode |= S_ISGID;
364
365         dir_dentry = v9fs_dentry_from_dir_inode(dir);
366         dfid = v9fs_fid_lookup(dir_dentry);
367         if (IS_ERR(dfid)) {
368                 err = PTR_ERR(dfid);
369                 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
370                 dfid = NULL;
371                 goto error;
372         }
373
374         gid = v9fs_get_fsgid_for_create(dir);
375         mode = omode;
376         /* Update mode based on ACL value */
377         err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
378         if (err) {
379                 P9_DPRINTK(P9_DEBUG_VFS,
380                            "Failed to get acl values in mkdir %d\n", err);
381                 goto error;
382         }
383         name = (char *) dentry->d_name.name;
384         err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
385         if (err < 0)
386                 goto error;
387
388         /* instantiate inode and assign the unopened fid to the dentry */
389         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
390                 fid = p9_client_walk(dfid, 1, &name, 1);
391                 if (IS_ERR(fid)) {
392                         err = PTR_ERR(fid);
393                         P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
394                                 err);
395                         fid = NULL;
396                         goto error;
397                 }
398
399                 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
400                 if (IS_ERR(inode)) {
401                         err = PTR_ERR(inode);
402                         P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
403                                 err);
404                         goto error;
405                 }
406                 d_instantiate(dentry, inode);
407                 err = v9fs_fid_add(dentry, fid);
408                 if (err < 0)
409                         goto error;
410                 fid = NULL;
411         } else {
412                 /*
413                  * Not in cached mode. No need to populate
414                  * inode with stat. We need to get an inode
415                  * so that we can set the acl with dentry
416                  */
417                 inode = v9fs_get_inode(dir->i_sb, mode);
418                 if (IS_ERR(inode)) {
419                         err = PTR_ERR(inode);
420                         goto error;
421                 }
422                 d_instantiate(dentry, inode);
423         }
424         /* Now set the ACL based on the default value */
425         v9fs_set_create_acl(dentry, &dacl, &pacl);
426         inc_nlink(dir);
427         v9fs_invalidate_inode_attr(dir);
428 error:
429         if (fid)
430                 p9_client_clunk(fid);
431         v9fs_set_create_acl(NULL, &dacl, &pacl);
432         return err;
433 }
434
435 static int
436 v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
437                  struct kstat *stat)
438 {
439         int err;
440         struct v9fs_session_info *v9ses;
441         struct p9_fid *fid;
442         struct p9_stat_dotl *st;
443
444         P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
445         err = -EPERM;
446         v9ses = v9fs_dentry2v9ses(dentry);
447         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
448                 generic_fillattr(dentry->d_inode, stat);
449                 return 0;
450         }
451         fid = v9fs_fid_lookup(dentry);
452         if (IS_ERR(fid))
453                 return PTR_ERR(fid);
454
455         /* Ask for all the fields in stat structure. Server will return
456          * whatever it supports
457          */
458
459         st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
460         if (IS_ERR(st))
461                 return PTR_ERR(st);
462
463         v9fs_stat2inode_dotl(st, dentry->d_inode);
464         generic_fillattr(dentry->d_inode, stat);
465         /* Change block size to what the server returned */
466         stat->blksize = st->st_blksize;
467
468         kfree(st);
469         return 0;
470 }
471
472 /**
473  * v9fs_vfs_setattr_dotl - set file metadata
474  * @dentry: file whose metadata to set
475  * @iattr: metadata assignment structure
476  *
477  */
478
479 int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
480 {
481         int retval;
482         struct v9fs_session_info *v9ses;
483         struct p9_fid *fid;
484         struct p9_iattr_dotl p9attr;
485
486         P9_DPRINTK(P9_DEBUG_VFS, "\n");
487
488         retval = inode_change_ok(dentry->d_inode, iattr);
489         if (retval)
490                 return retval;
491
492         p9attr.valid = iattr->ia_valid;
493         p9attr.mode = iattr->ia_mode;
494         p9attr.uid = iattr->ia_uid;
495         p9attr.gid = iattr->ia_gid;
496         p9attr.size = iattr->ia_size;
497         p9attr.atime_sec = iattr->ia_atime.tv_sec;
498         p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
499         p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
500         p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
501
502         retval = -EPERM;
503         v9ses = v9fs_dentry2v9ses(dentry);
504         fid = v9fs_fid_lookup(dentry);
505         if (IS_ERR(fid))
506                 return PTR_ERR(fid);
507
508         /* Write all dirty data */
509         if (S_ISREG(dentry->d_inode->i_mode))
510                 filemap_write_and_wait(dentry->d_inode->i_mapping);
511
512         retval = p9_client_setattr(fid, &p9attr);
513         if (retval < 0)
514                 return retval;
515
516         if ((iattr->ia_valid & ATTR_SIZE) &&
517             iattr->ia_size != i_size_read(dentry->d_inode))
518                 truncate_setsize(dentry->d_inode, iattr->ia_size);
519
520         v9fs_invalidate_inode_attr(dentry->d_inode);
521         setattr_copy(dentry->d_inode, iattr);
522         mark_inode_dirty(dentry->d_inode);
523         if (iattr->ia_valid & ATTR_MODE) {
524                 /* We also want to update ACL when we update mode bits */
525                 retval = v9fs_acl_chmod(dentry);
526                 if (retval < 0)
527                         return retval;
528         }
529         return 0;
530 }
531
532 /**
533  * v9fs_stat2inode_dotl - populate an inode structure with stat info
534  * @stat: stat structure
535  * @inode: inode to populate
536  * @sb: superblock of filesystem
537  *
538  */
539
540 void
541 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
542 {
543         struct v9fs_inode *v9inode = V9FS_I(inode);
544
545         if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
546                 inode->i_atime.tv_sec = stat->st_atime_sec;
547                 inode->i_atime.tv_nsec = stat->st_atime_nsec;
548                 inode->i_mtime.tv_sec = stat->st_mtime_sec;
549                 inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
550                 inode->i_ctime.tv_sec = stat->st_ctime_sec;
551                 inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
552                 inode->i_uid = stat->st_uid;
553                 inode->i_gid = stat->st_gid;
554                 inode->i_nlink = stat->st_nlink;
555                 inode->i_mode = stat->st_mode;
556                 inode->i_rdev = new_decode_dev(stat->st_rdev);
557
558                 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode)))
559                         init_special_inode(inode, inode->i_mode, inode->i_rdev);
560
561                 i_size_write(inode, stat->st_size);
562                 inode->i_blocks = stat->st_blocks;
563         } else {
564                 if (stat->st_result_mask & P9_STATS_ATIME) {
565                         inode->i_atime.tv_sec = stat->st_atime_sec;
566                         inode->i_atime.tv_nsec = stat->st_atime_nsec;
567                 }
568                 if (stat->st_result_mask & P9_STATS_MTIME) {
569                         inode->i_mtime.tv_sec = stat->st_mtime_sec;
570                         inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
571                 }
572                 if (stat->st_result_mask & P9_STATS_CTIME) {
573                         inode->i_ctime.tv_sec = stat->st_ctime_sec;
574                         inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
575                 }
576                 if (stat->st_result_mask & P9_STATS_UID)
577                         inode->i_uid = stat->st_uid;
578                 if (stat->st_result_mask & P9_STATS_GID)
579                         inode->i_gid = stat->st_gid;
580                 if (stat->st_result_mask & P9_STATS_NLINK)
581                         inode->i_nlink = stat->st_nlink;
582                 if (stat->st_result_mask & P9_STATS_MODE) {
583                         inode->i_mode = stat->st_mode;
584                         if ((S_ISBLK(inode->i_mode)) ||
585                                                 (S_ISCHR(inode->i_mode)))
586                                 init_special_inode(inode, inode->i_mode,
587                                                                 inode->i_rdev);
588                 }
589                 if (stat->st_result_mask & P9_STATS_RDEV)
590                         inode->i_rdev = new_decode_dev(stat->st_rdev);
591                 if (stat->st_result_mask & P9_STATS_SIZE)
592                         i_size_write(inode, stat->st_size);
593                 if (stat->st_result_mask & P9_STATS_BLOCKS)
594                         inode->i_blocks = stat->st_blocks;
595         }
596         if (stat->st_result_mask & P9_STATS_GEN)
597                 inode->i_generation = stat->st_gen;
598
599         /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
600          * because the inode structure does not have fields for them.
601          */
602         v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
603 }
604
605 static int
606 v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
607                 const char *symname)
608 {
609         int err;
610         gid_t gid;
611         char *name;
612         struct p9_qid qid;
613         struct inode *inode;
614         struct p9_fid *dfid;
615         struct p9_fid *fid = NULL;
616         struct v9fs_session_info *v9ses;
617
618         name = (char *) dentry->d_name.name;
619         P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n",
620                         dir->i_ino, name, symname);
621         v9ses = v9fs_inode2v9ses(dir);
622
623         dfid = v9fs_fid_lookup(dentry->d_parent);
624         if (IS_ERR(dfid)) {
625                 err = PTR_ERR(dfid);
626                 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
627                 return err;
628         }
629
630         gid = v9fs_get_fsgid_for_create(dir);
631
632         /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */
633         err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid);
634
635         if (err < 0) {
636                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err);
637                 goto error;
638         }
639
640         v9fs_invalidate_inode_attr(dir);
641         if (v9ses->cache) {
642                 /* Now walk from the parent so we can get an unopened fid. */
643                 fid = p9_client_walk(dfid, 1, &name, 1);
644                 if (IS_ERR(fid)) {
645                         err = PTR_ERR(fid);
646                         P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
647                                         err);
648                         fid = NULL;
649                         goto error;
650                 }
651
652                 /* instantiate inode and assign the unopened fid to dentry */
653                 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
654                 if (IS_ERR(inode)) {
655                         err = PTR_ERR(inode);
656                         P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
657                                         err);
658                         goto error;
659                 }
660                 d_instantiate(dentry, inode);
661                 err = v9fs_fid_add(dentry, fid);
662                 if (err < 0)
663                         goto error;
664                 fid = NULL;
665         } else {
666                 /* Not in cached mode. No need to populate inode with stat */
667                 inode = v9fs_get_inode(dir->i_sb, S_IFLNK);
668                 if (IS_ERR(inode)) {
669                         err = PTR_ERR(inode);
670                         goto error;
671                 }
672                 d_instantiate(dentry, inode);
673         }
674
675 error:
676         if (fid)
677                 p9_client_clunk(fid);
678
679         return err;
680 }
681
682 /**
683  * v9fs_vfs_link_dotl - create a hardlink for dotl
684  * @old_dentry: dentry for file to link to
685  * @dir: inode destination for new link
686  * @dentry: dentry for link
687  *
688  */
689
690 static int
691 v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
692                 struct dentry *dentry)
693 {
694         int err;
695         char *name;
696         struct dentry *dir_dentry;
697         struct p9_fid *dfid, *oldfid;
698         struct v9fs_session_info *v9ses;
699
700         P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n",
701                         dir->i_ino, old_dentry->d_name.name,
702                         dentry->d_name.name);
703
704         v9ses = v9fs_inode2v9ses(dir);
705         dir_dentry = v9fs_dentry_from_dir_inode(dir);
706         dfid = v9fs_fid_lookup(dir_dentry);
707         if (IS_ERR(dfid))
708                 return PTR_ERR(dfid);
709
710         oldfid = v9fs_fid_lookup(old_dentry);
711         if (IS_ERR(oldfid))
712                 return PTR_ERR(oldfid);
713
714         name = (char *) dentry->d_name.name;
715
716         err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name);
717
718         if (err < 0) {
719                 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
720                 return err;
721         }
722
723         v9fs_invalidate_inode_attr(dir);
724         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
725                 /* Get the latest stat info from server. */
726                 struct p9_fid *fid;
727                 fid = v9fs_fid_lookup(old_dentry);
728                 if (IS_ERR(fid))
729                         return PTR_ERR(fid);
730
731                 v9fs_refresh_inode_dotl(fid, old_dentry->d_inode);
732         }
733         ihold(old_dentry->d_inode);
734         d_instantiate(dentry, old_dentry->d_inode);
735
736         return err;
737 }
738
739 /**
740  * v9fs_vfs_mknod_dotl - create a special file
741  * @dir: inode destination for new link
742  * @dentry: dentry for file
743  * @mode: mode for creation
744  * @rdev: device associated with special file
745  *
746  */
747 static int
748 v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
749                 dev_t rdev)
750 {
751         int err;
752         gid_t gid;
753         char *name;
754         umode_t mode;
755         struct v9fs_session_info *v9ses;
756         struct p9_fid *fid = NULL, *dfid = NULL;
757         struct inode *inode;
758         struct p9_qid qid;
759         struct dentry *dir_dentry;
760         struct posix_acl *dacl = NULL, *pacl = NULL;
761
762         P9_DPRINTK(P9_DEBUG_VFS,
763                 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
764                 dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev));
765
766         if (!new_valid_dev(rdev))
767                 return -EINVAL;
768
769         v9ses = v9fs_inode2v9ses(dir);
770         dir_dentry = v9fs_dentry_from_dir_inode(dir);
771         dfid = v9fs_fid_lookup(dir_dentry);
772         if (IS_ERR(dfid)) {
773                 err = PTR_ERR(dfid);
774                 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
775                 dfid = NULL;
776                 goto error;
777         }
778
779         gid = v9fs_get_fsgid_for_create(dir);
780         mode = omode;
781         /* Update mode based on ACL value */
782         err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
783         if (err) {
784                 P9_DPRINTK(P9_DEBUG_VFS,
785                            "Failed to get acl values in mknod %d\n", err);
786                 goto error;
787         }
788         name = (char *) dentry->d_name.name;
789
790         err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
791         if (err < 0)
792                 goto error;
793
794         v9fs_invalidate_inode_attr(dir);
795         /* instantiate inode and assign the unopened fid to the dentry */
796         if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
797                 fid = p9_client_walk(dfid, 1, &name, 1);
798                 if (IS_ERR(fid)) {
799                         err = PTR_ERR(fid);
800                         P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
801                                 err);
802                         fid = NULL;
803                         goto error;
804                 }
805
806                 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
807                 if (IS_ERR(inode)) {
808                         err = PTR_ERR(inode);
809                         P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
810                                 err);
811                         goto error;
812                 }
813                 d_instantiate(dentry, inode);
814                 err = v9fs_fid_add(dentry, fid);
815                 if (err < 0)
816                         goto error;
817                 fid = NULL;
818         } else {
819                 /*
820                  * Not in cached mode. No need to populate inode with stat.
821                  * socket syscall returns a fd, so we need instantiate
822                  */
823                 inode = v9fs_get_inode(dir->i_sb, mode);
824                 if (IS_ERR(inode)) {
825                         err = PTR_ERR(inode);
826                         goto error;
827                 }
828                 d_instantiate(dentry, inode);
829         }
830         /* Now set the ACL based on the default value */
831         v9fs_set_create_acl(dentry, &dacl, &pacl);
832 error:
833         if (fid)
834                 p9_client_clunk(fid);
835         v9fs_set_create_acl(NULL, &dacl, &pacl);
836         return err;
837 }
838
839 /**
840  * v9fs_vfs_follow_link_dotl - follow a symlink path
841  * @dentry: dentry for symlink
842  * @nd: nameidata
843  *
844  */
845
846 static void *
847 v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
848 {
849         int retval;
850         struct p9_fid *fid;
851         char *link = __getname();
852         char *target;
853
854         P9_DPRINTK(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);
855
856         if (!link) {
857                 link = ERR_PTR(-ENOMEM);
858                 goto ndset;
859         }
860         fid = v9fs_fid_lookup(dentry);
861         if (IS_ERR(fid)) {
862                 __putname(link);
863                 link = ERR_CAST(fid);
864                 goto ndset;
865         }
866         retval = p9_client_readlink(fid, &target);
867         if (!retval) {
868                 strcpy(link, target);
869                 kfree(target);
870                 goto ndset;
871         }
872         __putname(link);
873         link = ERR_PTR(retval);
874 ndset:
875         nd_set_link(nd, link);
876         return NULL;
877 }
878
879 int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
880 {
881         loff_t i_size;
882         struct p9_stat_dotl *st;
883         struct v9fs_session_info *v9ses;
884
885         v9ses = v9fs_inode2v9ses(inode);
886         st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
887         if (IS_ERR(st))
888                 return PTR_ERR(st);
889
890         spin_lock(&inode->i_lock);
891         /*
892          * We don't want to refresh inode->i_size,
893          * because we may have cached data
894          */
895         i_size = inode->i_size;
896         v9fs_stat2inode_dotl(st, inode);
897         if (v9ses->cache)
898                 inode->i_size = i_size;
899         spin_unlock(&inode->i_lock);
900         kfree(st);
901         return 0;
902 }
903
904 const struct inode_operations v9fs_dir_inode_operations_dotl = {
905         .create = v9fs_vfs_create_dotl,
906         .lookup = v9fs_vfs_lookup,
907         .link = v9fs_vfs_link_dotl,
908         .symlink = v9fs_vfs_symlink_dotl,
909         .unlink = v9fs_vfs_unlink,
910         .mkdir = v9fs_vfs_mkdir_dotl,
911         .rmdir = v9fs_vfs_rmdir,
912         .mknod = v9fs_vfs_mknod_dotl,
913         .rename = v9fs_vfs_rename,
914         .getattr = v9fs_vfs_getattr_dotl,
915         .setattr = v9fs_vfs_setattr_dotl,
916         .setxattr = generic_setxattr,
917         .getxattr = generic_getxattr,
918         .removexattr = generic_removexattr,
919         .listxattr = v9fs_listxattr,
920         .get_acl = v9fs_iop_get_acl,
921 };
922
923 const struct inode_operations v9fs_file_inode_operations_dotl = {
924         .getattr = v9fs_vfs_getattr_dotl,
925         .setattr = v9fs_vfs_setattr_dotl,
926         .setxattr = generic_setxattr,
927         .getxattr = generic_getxattr,
928         .removexattr = generic_removexattr,
929         .listxattr = v9fs_listxattr,
930         .get_acl = v9fs_iop_get_acl,
931 };
932
933 const struct inode_operations v9fs_symlink_inode_operations_dotl = {
934         .readlink = generic_readlink,
935         .follow_link = v9fs_vfs_follow_link_dotl,
936         .put_link = v9fs_vfs_put_link,
937         .getattr = v9fs_vfs_getattr_dotl,
938         .setattr = v9fs_vfs_setattr_dotl,
939         .setxattr = generic_setxattr,
940         .getxattr = generic_getxattr,
941         .removexattr = generic_removexattr,
942         .listxattr = v9fs_listxattr,
943 };