blob: 8f68280d752e2e49b0c1ae366937f56274072022 [file] [log] [blame]
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001/*
2 * linux/fs/9p/vfs_inode.c
3 *
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07004 * This file contains vfs inode ops for the 9P2000 protocol.
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07005 *
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
Eric Van Hensbergen42e8c502006-03-25 03:07:28 -080010 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation.
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070012 *
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>
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070033#include <linux/inet.h>
34#include <linux/namei.h>
35#include <linux/idr.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040036#include <linux/sched.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090037#include <linux/slab.h>
Aneesh Kumar K.Vebf46262010-05-31 13:22:56 +053038#include <linux/xattr.h>
Aneesh Kumar K.V85ff8722010-09-28 00:27:39 +053039#include <linux/posix_acl.h>
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050040#include <net/9p/9p.h>
41#include <net/9p/client.h>
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070042
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070043#include "v9fs.h"
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070044#include "v9fs_vfs.h"
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070045#include "fid.h"
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -050046#include "cache.h"
Aneesh Kumar K.Vebf46262010-05-31 13:22:56 +053047#include "xattr.h"
Aneesh Kumar K.V85ff8722010-09-28 00:27:39 +053048#include "acl.h"
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070049
Arjan van de Ven754661f2007-02-12 00:55:38 -080050static const struct inode_operations v9fs_dir_inode_operations;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +000051static const struct inode_operations v9fs_dir_inode_operations_dotu;
52static const struct inode_operations v9fs_dir_inode_operations_dotl;
Arjan van de Ven754661f2007-02-12 00:55:38 -080053static const struct inode_operations v9fs_file_inode_operations;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +000054static const struct inode_operations v9fs_file_inode_operations_dotl;
Arjan van de Ven754661f2007-02-12 00:55:38 -080055static const struct inode_operations v9fs_symlink_inode_operations;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +000056static const struct inode_operations v9fs_symlink_inode_operations_dotl;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070057
Aneesh Kumar K.Vf5fc6142010-10-12 13:02:25 +053058static int
59v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
60 dev_t rdev);
61
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070062/**
63 * unixmode2p9mode - convert unix mode bits to plan 9
64 * @v9ses: v9fs session information
65 * @mode: mode to convert
66 *
67 */
68
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -070069static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070070{
71 int res;
72 res = mode & 0777;
73 if (S_ISDIR(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050074 res |= P9_DMDIR;
Sripathi Kodidd6102f2010-03-05 18:48:00 +000075 if (v9fs_proto_dotu(v9ses)) {
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070076 if (S_ISLNK(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050077 res |= P9_DMSYMLINK;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070078 if (v9ses->nodev == 0) {
79 if (S_ISSOCK(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050080 res |= P9_DMSOCKET;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070081 if (S_ISFIFO(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050082 res |= P9_DMNAMEDPIPE;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070083 if (S_ISBLK(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050084 res |= P9_DMDEVICE;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070085 if (S_ISCHR(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050086 res |= P9_DMDEVICE;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070087 }
88
89 if ((mode & S_ISUID) == S_ISUID)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050090 res |= P9_DMSETUID;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070091 if ((mode & S_ISGID) == S_ISGID)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050092 res |= P9_DMSETGID;
Anthony Liguorid199d652008-02-06 19:25:06 -060093 if ((mode & S_ISVTX) == S_ISVTX)
94 res |= P9_DMSETVTX;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050095 if ((mode & P9_DMLINK))
96 res |= P9_DMLINK;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070097 }
98
99 return res;
100}
101
102/**
103 * p9mode2unixmode- convert plan9 mode bits to unix mode bits
104 * @v9ses: v9fs session information
105 * @mode: mode to convert
106 *
107 */
108
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -0700109static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700110{
111 int res;
112
113 res = mode & 0777;
114
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500115 if ((mode & P9_DMDIR) == P9_DMDIR)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700116 res |= S_IFDIR;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000117 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700118 res |= S_IFLNK;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000119 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700120 && (v9ses->nodev == 0))
121 res |= S_IFSOCK;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000122 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700123 && (v9ses->nodev == 0))
124 res |= S_IFIFO;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000125 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700126 && (v9ses->nodev == 0))
127 res |= S_IFBLK;
128 else
129 res |= S_IFREG;
130
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000131 if (v9fs_proto_dotu(v9ses)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500132 if ((mode & P9_DMSETUID) == P9_DMSETUID)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700133 res |= S_ISUID;
134
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500135 if ((mode & P9_DMSETGID) == P9_DMSETGID)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700136 res |= S_ISGID;
Anthony Liguorid199d652008-02-06 19:25:06 -0600137
138 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
139 res |= S_ISVTX;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700140 }
141
142 return res;
143}
144
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600145/**
146 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
147 * @uflags: flags to convert
Eric Van Hensbergen2e4bef42008-06-24 17:39:39 -0500148 * @extended: if .u extensions are active
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600149 */
150
Eric Van Hensbergen2e4bef42008-06-24 17:39:39 -0500151int v9fs_uflags2omode(int uflags, int extended)
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800152{
153 int ret;
154
155 ret = 0;
156 switch (uflags&3) {
157 default:
158 case O_RDONLY:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500159 ret = P9_OREAD;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800160 break;
161
162 case O_WRONLY:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500163 ret = P9_OWRITE;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800164 break;
165
166 case O_RDWR:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500167 ret = P9_ORDWR;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800168 break;
169 }
170
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800171 if (uflags & O_TRUNC)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500172 ret |= P9_OTRUNC;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800173
Eric Van Hensbergen2e4bef42008-06-24 17:39:39 -0500174 if (extended) {
175 if (uflags & O_EXCL)
176 ret |= P9_OEXCL;
177
178 if (uflags & O_APPEND)
179 ret |= P9_OAPPEND;
180 }
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800181
182 return ret;
183}
184
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700185/**
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800186 * v9fs_blank_wstat - helper function to setup a 9P stat structure
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800187 * @wstat: structure to initialize
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700188 *
189 */
190
M. Mohan Kumar7a4439c2010-02-08 15:36:48 -0600191void
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500192v9fs_blank_wstat(struct p9_wstat *wstat)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700193{
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800194 wstat->type = ~0;
195 wstat->dev = ~0;
196 wstat->qid.type = ~0;
197 wstat->qid.version = ~0;
198 *((long long *)&wstat->qid.path) = ~0;
199 wstat->mode = ~0;
200 wstat->atime = ~0;
201 wstat->mtime = ~0;
202 wstat->length = ~0;
203 wstat->name = NULL;
204 wstat->uid = NULL;
205 wstat->gid = NULL;
206 wstat->muid = NULL;
207 wstat->n_uid = ~0;
208 wstat->n_gid = ~0;
209 wstat->n_muid = ~0;
210 wstat->extension = NULL;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700211}
212
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500213#ifdef CONFIG_9P_FSCACHE
214/**
215 * v9fs_alloc_inode - helper function to allocate an inode
216 * This callback is executed before setting up the inode so that we
217 * can associate a vcookie with each inode.
218 *
219 */
220
221struct inode *v9fs_alloc_inode(struct super_block *sb)
222{
223 struct v9fs_cookie *vcookie;
224 vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
225 GFP_KERNEL);
226 if (!vcookie)
227 return NULL;
228
229 vcookie->fscache = NULL;
230 vcookie->qid = NULL;
231 spin_lock_init(&vcookie->lock);
232 return &vcookie->inode;
233}
234
235/**
236 * v9fs_destroy_inode - destroy an inode
237 *
238 */
239
240void v9fs_destroy_inode(struct inode *inode)
241{
242 kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
243}
244#endif
245
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700246/**
Eric Van Hensbergen09d34ee2010-08-02 14:28:09 -0500247 * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a
248 * new file system object. This checks the S_ISGID to determine the owning
249 * group of the new file system object.
250 */
251
252static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
253{
254 BUG_ON(dir_inode == NULL);
255
256 if (dir_inode->i_mode & S_ISGID) {
257 /* set_gid bit is set.*/
258 return dir_inode->i_gid;
259 }
260 return current_fsgid();
261}
262
263/**
264 * v9fs_dentry_from_dir_inode - helper function to get the dentry from
265 * dir inode.
266 *
267 */
268
Eric Van Hensbergenea1375332010-07-27 14:49:43 -0500269static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
Eric Van Hensbergen09d34ee2010-08-02 14:28:09 -0500270{
271 struct dentry *dentry;
272
273 spin_lock(&dcache_lock);
274 /* Directory should have only one entry. */
275 BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
276 dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
277 spin_unlock(&dcache_lock);
278 return dentry;
279}
280
281/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700282 * v9fs_get_inode - helper function to setup an inode
283 * @sb: superblock
284 * @mode: mode to setup inode with
285 *
286 */
287
288struct inode *v9fs_get_inode(struct super_block *sb, int mode)
289{
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600290 int err;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800291 struct inode *inode;
Eric Van Hensbergenb5016112005-09-09 13:04:27 -0700292 struct v9fs_session_info *v9ses = sb->s_fs_info;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700293
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500294 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700295
296 inode = new_inode(sb);
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600297 if (!inode) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500298 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
Abhishek Kulkarni48559b4c2009-08-17 16:32:18 -0500299 return ERR_PTR(-ENOMEM);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700300 }
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600301
Dmitry Monakhov217f2062010-03-04 17:30:57 +0300302 inode_init_owner(inode, NULL, mode);
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600303 inode->i_blocks = 0;
304 inode->i_rdev = 0;
305 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
306 inode->i_mapping->a_ops = &v9fs_addr_operations;
307
308 switch (mode & S_IFMT) {
309 case S_IFIFO:
310 case S_IFBLK:
311 case S_IFCHR:
312 case S_IFSOCK:
M. Mohan Kumar4b435162010-06-16 14:27:01 +0530313 if (v9fs_proto_dotl(v9ses)) {
314 inode->i_op = &v9fs_file_inode_operations_dotl;
315 inode->i_fop = &v9fs_file_operations_dotl;
316 } else if (v9fs_proto_dotu(v9ses)) {
317 inode->i_op = &v9fs_file_inode_operations;
318 inode->i_fop = &v9fs_file_operations;
319 } else {
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600320 P9_DPRINTK(P9_DEBUG_ERROR,
321 "special files without extended mode\n");
322 err = -EINVAL;
323 goto error;
324 }
325 init_special_inode(inode, inode->i_mode, inode->i_rdev);
326 break;
327 case S_IFREG:
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000328 if (v9fs_proto_dotl(v9ses)) {
329 inode->i_op = &v9fs_file_inode_operations_dotl;
330 inode->i_fop = &v9fs_file_operations_dotl;
331 } else {
332 inode->i_op = &v9fs_file_inode_operations;
333 inode->i_fop = &v9fs_file_operations;
334 }
335
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600336 break;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000337
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600338 case S_IFLNK:
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000339 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
340 P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with "
341 "legacy protocol.\n");
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600342 err = -EINVAL;
343 goto error;
344 }
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000345
346 if (v9fs_proto_dotl(v9ses))
347 inode->i_op = &v9fs_symlink_inode_operations_dotl;
348 else
349 inode->i_op = &v9fs_symlink_inode_operations;
350
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600351 break;
352 case S_IFDIR:
353 inc_nlink(inode);
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000354 if (v9fs_proto_dotl(v9ses))
355 inode->i_op = &v9fs_dir_inode_operations_dotl;
356 else if (v9fs_proto_dotu(v9ses))
357 inode->i_op = &v9fs_dir_inode_operations_dotu;
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600358 else
359 inode->i_op = &v9fs_dir_inode_operations;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000360
361 if (v9fs_proto_dotl(v9ses))
362 inode->i_fop = &v9fs_dir_operations_dotl;
363 else
364 inode->i_fop = &v9fs_dir_operations;
365
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600366 break;
367 default:
368 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
369 mode, mode & S_IFMT);
370 err = -EINVAL;
371 goto error;
372 }
373
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700374 return inode;
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600375
376error:
377 iput(inode);
378 return ERR_PTR(err);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700379}
380
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500381/*
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800382static struct v9fs_fid*
383v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
384{
385 int err;
Mika Kukkonen736c4b82006-12-06 20:36:29 -0800386 int nfid;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800387 struct v9fs_fid *ret;
388 struct v9fs_fcall *fcall;
389
390 nfid = v9fs_get_idpool(&v9ses->fidpool);
391 if (nfid < 0) {
392 eprintk(KERN_WARNING, "no free fids available\n");
Latchesar Ionkov731805b2006-03-07 21:55:42 -0800393 return ERR_PTR(-ENOSPC);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800394 }
395
396 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
397 &fcall);
398
399 if (err < 0) {
Latchesar Ionkov41e5a6a2006-05-15 09:44:21 -0700400 if (fcall && fcall->id == RWALK)
401 goto clunk_fid;
402
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800403 PRINT_FCALL_ERROR("walk error", fcall);
404 v9fs_put_idpool(nfid, &v9ses->fidpool);
405 goto error;
406 }
407
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700408 kfree(fcall);
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800409 fcall = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800410 ret = v9fs_fid_create(v9ses, nfid);
411 if (!ret) {
412 err = -ENOMEM;
413 goto clunk_fid;
414 }
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700415
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800416 err = v9fs_fid_insert(ret, dentry);
417 if (err < 0) {
418 v9fs_fid_destroy(ret);
419 goto clunk_fid;
Latchesar Ionkov0b8dd172005-09-27 21:45:24 -0700420 }
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800421
422 return ret;
423
424clunk_fid:
425 v9fs_t_clunk(v9ses, nfid);
426
427error:
428 kfree(fcall);
429 return ERR_PTR(err);
430}
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500431*/
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800432
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500433
434/**
435 * v9fs_clear_inode - release an inode
436 * @inode: inode to release
437 *
438 */
Al Virob57922d2010-06-07 14:34:48 -0400439void v9fs_evict_inode(struct inode *inode)
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500440{
Al Virob57922d2010-06-07 14:34:48 -0400441 truncate_inode_pages(inode->i_mapping, 0);
442 end_writeback(inode);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500443 filemap_fdatawrite(inode->i_mapping);
444
445#ifdef CONFIG_9P_FSCACHE
446 v9fs_cache_inode_put_cookie(inode);
447#endif
448}
449
Latchesar Ionkov5174fda2006-03-25 03:07:25 -0800450static struct inode *
Sripathi Kodif0853122010-07-12 20:07:23 +0530451v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid,
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800452 struct super_block *sb)
453{
454 int err, umode;
Sripathi Kodif0853122010-07-12 20:07:23 +0530455 struct inode *ret = NULL;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500456 struct p9_wstat *st;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800457
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500458 st = p9_client_stat(fid);
Abhishek Kulkarni02bc3562009-07-19 13:41:54 -0600459 if (IS_ERR(st))
460 return ERR_CAST(st);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800461
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500462 umode = p9mode2unixmode(v9ses, st->mode);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800463 ret = v9fs_get_inode(sb, umode);
464 if (IS_ERR(ret)) {
465 err = PTR_ERR(ret);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800466 goto error;
467 }
468
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500469 v9fs_stat2inode(st, ret, sb);
470 ret->i_ino = v9fs_qid2ino(&st->qid);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500471
472#ifdef CONFIG_9P_FSCACHE
473 v9fs_vcookie_set_qid(ret, &st->qid);
474 v9fs_cache_inode_get_cookie(ret);
475#endif
Abhishek Kulkarni02bc3562009-07-19 13:41:54 -0600476 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500477 kfree(st);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800478 return ret;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800479error:
Abhishek Kulkarni02bc3562009-07-19 13:41:54 -0600480 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500481 kfree(st);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800482 return ERR_PTR(err);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700483}
484
Sripathi Kodif0853122010-07-12 20:07:23 +0530485static struct inode *
486v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
487 struct super_block *sb)
488{
489 struct inode *ret = NULL;
490 int err;
491 struct p9_stat_dotl *st;
492
493 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
494 if (IS_ERR(st))
495 return ERR_CAST(st);
496
497 ret = v9fs_get_inode(sb, st->st_mode);
498 if (IS_ERR(ret)) {
499 err = PTR_ERR(ret);
500 goto error;
501 }
502
503 v9fs_stat2inode_dotl(st, ret);
504 ret->i_ino = v9fs_qid2ino(&st->qid);
505#ifdef CONFIG_9P_FSCACHE
506 v9fs_vcookie_set_qid(ret, &st->qid);
507 v9fs_cache_inode_get_cookie(ret);
508#endif
Aneesh Kumar K.V85ff8722010-09-28 00:27:39 +0530509 err = v9fs_get_acl(ret, fid);
510 if (err) {
511 iput(ret);
512 goto error;
513 }
Sripathi Kodif0853122010-07-12 20:07:23 +0530514 kfree(st);
515 return ret;
516error:
517 kfree(st);
518 return ERR_PTR(err);
519}
520
521/**
522 * v9fs_inode_from_fid - Helper routine to populate an inode by
523 * issuing a attribute request
524 * @v9ses: session information
525 * @fid: fid to issue attribute request for
526 * @sb: superblock on which to create inode
527 *
528 */
529static inline struct inode *
530v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
531 struct super_block *sb)
532{
533 if (v9fs_proto_dotl(v9ses))
534 return v9fs_inode_dotl(v9ses, fid, sb);
535 else
536 return v9fs_inode(v9ses, fid, sb);
537}
538
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700539/**
540 * v9fs_remove - helper function to remove files and directories
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -0700541 * @dir: directory inode that is being deleted
542 * @file: dentry that is being deleted
543 * @rmdir: removing a directory
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700544 *
545 */
546
547static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
548{
Aneesh Kumar K.Vd994f402010-03-29 18:14:50 -0500549 int retval;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500550 struct inode *file_inode;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500551 struct p9_fid *v9fid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700552
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500553 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700554 rmdir);
555
556 file_inode = file->d_inode;
Latchesar Ionkovc959df92007-04-23 14:41:11 -0700557 v9fid = v9fs_fid_clone(file);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500558 if (IS_ERR(v9fid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800559 return PTR_ERR(v9fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700560
Aneesh Kumar K.Vd994f402010-03-29 18:14:50 -0500561 retval = p9_client_remove(v9fid);
562 if (!retval)
563 drop_nlink(file_inode);
564 return retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700565}
566
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800567static int
568v9fs_open_created(struct inode *inode, struct file *file)
569{
570 return 0;
571}
572
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500573
574/**
575 * v9fs_create - Create a file
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600576 * @v9ses: session information
577 * @dir: directory that dentry is being created in
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500578 * @dentry: dentry that is being created
Abhishek Kulkarni0e155972009-07-19 13:41:55 -0600579 * @extension: 9p2000.u extension string to support devices, etc.
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500580 * @perm: create permissions
581 * @mode: open mode
582 *
583 */
584static struct p9_fid *
585v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
586 struct dentry *dentry, char *extension, u32 perm, u8 mode)
587{
588 int err;
589 char *name;
590 struct p9_fid *dfid, *ofid, *fid;
591 struct inode *inode;
592
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500593 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
594
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500595 err = 0;
596 ofid = NULL;
597 fid = NULL;
598 name = (char *) dentry->d_name.name;
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000599 dfid = v9fs_fid_lookup(dentry->d_parent);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500600 if (IS_ERR(dfid)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500601 err = PTR_ERR(dfid);
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000602 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
603 return ERR_PTR(err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500604 }
605
606 /* clone a fid to use for creation */
607 ofid = p9_client_walk(dfid, 0, NULL, 1);
608 if (IS_ERR(ofid)) {
609 err = PTR_ERR(ofid);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500610 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000611 return ERR_PTR(err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500612 }
613
614 err = p9_client_fcreate(ofid, name, perm, mode, extension);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500615 if (err < 0) {
616 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500617 goto error;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500618 }
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500619
620 /* now walk from the parent so we can get unopened fid */
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000621 fid = p9_client_walk(dfid, 1, &name, 1);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500622 if (IS_ERR(fid)) {
623 err = PTR_ERR(fid);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500624 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500625 fid = NULL;
626 goto error;
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000627 }
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500628
629 /* instantiate inode and assign the unopened fid to the dentry */
630 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
631 if (IS_ERR(inode)) {
632 err = PTR_ERR(inode);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500633 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500634 goto error;
635 }
636
Latchesar Ionkovba176742007-10-17 14:31:07 -0500637 if (v9ses->cache)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500638 dentry->d_op = &v9fs_cached_dentry_operations;
639 else
640 dentry->d_op = &v9fs_dentry_operations;
641
642 d_instantiate(dentry, inode);
Abhishek Kulkarni50fb6d22009-07-19 13:41:57 -0600643 err = v9fs_fid_add(dentry, fid);
644 if (err < 0)
645 goto error;
646
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500647 return ofid;
648
649error:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500650 if (ofid)
651 p9_client_clunk(ofid);
652
653 if (fid)
654 p9_client_clunk(fid);
655
656 return ERR_PTR(err);
657}
658
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700659/**
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700660 * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
661 * @dir: directory inode that is being created
662 * @dentry: dentry that is being deleted
663 * @mode: create permissions
664 * @nd: path information
665 *
666 */
667
668static int
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530669v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700670 struct nameidata *nd)
671{
672 int err = 0;
673 char *name = NULL;
674 gid_t gid;
675 int flags;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530676 mode_t mode;
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700677 struct v9fs_session_info *v9ses;
678 struct p9_fid *fid = NULL;
679 struct p9_fid *dfid, *ofid;
680 struct file *filp;
681 struct p9_qid qid;
682 struct inode *inode;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530683 struct posix_acl *pacl = NULL, *dacl = NULL;
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700684
685 v9ses = v9fs_inode2v9ses(dir);
686 if (nd && nd->flags & LOOKUP_OPEN)
687 flags = nd->intent.open.flags - 1;
Aneesh Kumar K.Vf5fc6142010-10-12 13:02:25 +0530688 else {
689 /*
690 * create call without LOOKUP_OPEN is due
691 * to mknod of regular files. So use mknod
692 * operation.
693 */
694 return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
695 }
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700696
697 name = (char *) dentry->d_name.name;
698 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x "
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530699 "mode:0x%x\n", name, flags, omode);
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700700
701 dfid = v9fs_fid_lookup(dentry->d_parent);
702 if (IS_ERR(dfid)) {
703 err = PTR_ERR(dfid);
704 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
705 return err;
706 }
707
708 /* clone a fid to use for creation */
709 ofid = p9_client_walk(dfid, 0, NULL, 1);
710 if (IS_ERR(ofid)) {
711 err = PTR_ERR(ofid);
712 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
713 return err;
714 }
715
716 gid = v9fs_get_fsgid_for_create(dir);
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530717
718 mode = omode;
719 /* Update mode based on ACL value */
720 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
721 if (err) {
722 P9_DPRINTK(P9_DEBUG_VFS,
723 "Failed to get acl values in creat %d\n", err);
724 goto error;
725 }
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700726 err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
727 if (err < 0) {
728 P9_DPRINTK(P9_DEBUG_VFS,
729 "p9_client_open_dotl failed in creat %d\n",
730 err);
731 goto error;
732 }
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530733 /* instantiate inode and assign the unopened fid to the dentry */
734 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE ||
735 (nd && nd->flags & LOOKUP_OPEN)) {
736 fid = p9_client_walk(dfid, 1, &name, 1);
737 if (IS_ERR(fid)) {
738 err = PTR_ERR(fid);
739 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
740 err);
741 fid = NULL;
742 goto error;
743 }
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700744
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530745 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
746 if (IS_ERR(inode)) {
747 err = PTR_ERR(inode);
748 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
749 err);
750 goto error;
751 }
Aneesh Kumar K.V3c307502010-08-30 16:04:35 +0000752 dentry->d_op = &v9fs_cached_dentry_operations;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530753 d_instantiate(dentry, inode);
754 err = v9fs_fid_add(dentry, fid);
755 if (err < 0)
756 goto error;
757 /* The fid would get clunked via a dput */
758 fid = NULL;
759 } else {
760 /*
761 * Not in cached mode. No need to populate
762 * inode with stat. We need to get an inode
763 * so that we can set the acl with dentry
764 */
765 inode = v9fs_get_inode(dir->i_sb, mode);
766 if (IS_ERR(inode)) {
767 err = PTR_ERR(inode);
768 goto error;
769 }
Aneesh Kumar K.V3c307502010-08-30 16:04:35 +0000770 dentry->d_op = &v9fs_dentry_operations;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530771 d_instantiate(dentry, inode);
772 }
773 /* Now set the ACL based on the default value */
774 v9fs_set_create_acl(dentry, dacl, pacl);
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -0700775
776 /* if we are opening a file, assign the open fid to the file */
777 if (nd && nd->flags & LOOKUP_OPEN) {
778 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
779 if (IS_ERR(filp)) {
780 p9_client_clunk(ofid);
781 return PTR_ERR(filp);
782 }
783 filp->private_data = ofid;
784 } else
785 p9_client_clunk(ofid);
786
787 return 0;
788
789error:
790 if (ofid)
791 p9_client_clunk(ofid);
792 if (fid)
793 p9_client_clunk(fid);
794 return err;
795}
796
797/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700798 * v9fs_vfs_create - VFS hook to create files
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600799 * @dir: directory inode that is being created
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700800 * @dentry: dentry that is being deleted
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800801 * @mode: create permissions
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700802 * @nd: path information
803 *
804 */
805
806static int
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800807v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700808 struct nameidata *nd)
809{
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800810 int err;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500811 u32 perm;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800812 int flags;
813 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500814 struct p9_fid *fid;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800815 struct file *filp;
816
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500817 err = 0;
818 fid = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800819 v9ses = v9fs_inode2v9ses(dir);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800820 perm = unixmode2p9mode(v9ses, mode);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800821 if (nd && nd->flags & LOOKUP_OPEN)
822 flags = nd->intent.open.flags - 1;
823 else
824 flags = O_RDWR;
825
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500826 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000827 v9fs_uflags2omode(flags,
828 v9fs_proto_dotu(v9ses)));
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500829 if (IS_ERR(fid)) {
830 err = PTR_ERR(fid);
831 fid = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800832 goto error;
833 }
834
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500835 /* if we are opening a file, assign the open fid to the file */
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800836 if (nd && nd->flags & LOOKUP_OPEN) {
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800837 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
838 if (IS_ERR(filp)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500839 err = PTR_ERR(filp);
840 goto error;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800841 }
842
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500843 filp->private_data = fid;
844 } else
845 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800846
847 return 0;
848
849error:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500850 if (fid)
851 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800852
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800853 return err;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700854}
855
856/**
857 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600858 * @dir: inode that is being unlinked
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700859 * @dentry: dentry that is being unlinked
860 * @mode: mode for new directory
861 *
862 */
863
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800864static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700865{
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800866 int err;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500867 u32 perm;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800868 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500869 struct p9_fid *fid;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800870
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500871 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
872 err = 0;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800873 v9ses = v9fs_inode2v9ses(dir);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800874 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500875 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
876 if (IS_ERR(fid)) {
877 err = PTR_ERR(fid);
878 fid = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800879 }
880
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500881 if (fid)
882 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800883
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800884 return err;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700885}
886
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530887
888/**
889 * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory
890 * @dir: inode that is being unlinked
891 * @dentry: dentry that is being unlinked
892 * @mode: mode for new directory
893 *
894 */
895
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530896static int v9fs_vfs_mkdir_dotl(struct inode *dir,
897 struct dentry *dentry, int omode)
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530898{
899 int err;
900 struct v9fs_session_info *v9ses;
901 struct p9_fid *fid = NULL, *dfid = NULL;
902 gid_t gid;
903 char *name;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530904 mode_t mode;
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530905 struct inode *inode;
906 struct p9_qid qid;
907 struct dentry *dir_dentry;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530908 struct posix_acl *dacl = NULL, *pacl = NULL;
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530909
910 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
911 err = 0;
912 v9ses = v9fs_inode2v9ses(dir);
913
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530914 omode |= S_IFDIR;
Harsh Prateek Bora7c7298c2010-08-18 06:01:52 +0000915 if (dir->i_mode & S_ISGID)
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530916 omode |= S_ISGID;
917
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530918 dir_dentry = v9fs_dentry_from_dir_inode(dir);
919 dfid = v9fs_fid_lookup(dir_dentry);
920 if (IS_ERR(dfid)) {
921 err = PTR_ERR(dfid);
922 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
923 dfid = NULL;
924 goto error;
925 }
926
927 gid = v9fs_get_fsgid_for_create(dir);
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530928 mode = omode;
929 /* Update mode based on ACL value */
930 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
931 if (err) {
932 P9_DPRINTK(P9_DEBUG_VFS,
933 "Failed to get acl values in mkdir %d\n", err);
934 goto error;
935 }
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530936 name = (char *) dentry->d_name.name;
937 err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
938 if (err < 0)
939 goto error;
940
941 /* instantiate inode and assign the unopened fid to the dentry */
942 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
943 fid = p9_client_walk(dfid, 1, &name, 1);
944 if (IS_ERR(fid)) {
945 err = PTR_ERR(fid);
946 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
947 err);
948 fid = NULL;
949 goto error;
950 }
951
952 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
953 if (IS_ERR(inode)) {
954 err = PTR_ERR(inode);
955 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
956 err);
957 goto error;
958 }
959 dentry->d_op = &v9fs_cached_dentry_operations;
960 d_instantiate(dentry, inode);
961 err = v9fs_fid_add(dentry, fid);
962 if (err < 0)
963 goto error;
964 fid = NULL;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530965 } else {
966 /*
967 * Not in cached mode. No need to populate
968 * inode with stat. We need to get an inode
969 * so that we can set the acl with dentry
970 */
971 inode = v9fs_get_inode(dir->i_sb, mode);
972 if (IS_ERR(inode)) {
973 err = PTR_ERR(inode);
974 goto error;
975 }
976 dentry->d_op = &v9fs_dentry_operations;
977 d_instantiate(dentry, inode);
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530978 }
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +0530979 /* Now set the ACL based on the default value */
980 v9fs_set_create_acl(dentry, dacl, pacl);
981
M. Mohan Kumar01a622b2010-06-16 14:27:22 +0530982error:
983 if (fid)
984 p9_client_clunk(fid);
985 return err;
986}
987
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700988/**
989 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
990 * @dir: inode that is being walked from
991 * @dentry: dentry that is being walked to?
992 * @nameidata: path data
993 *
994 */
995
996static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
997 struct nameidata *nameidata)
998{
999 struct super_block *sb;
1000 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001001 struct p9_fid *dfid, *fid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001002 struct inode *inode;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001003 char *name;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001004 int result = 0;
1005
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001006 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
Latchesar Ionkov731805b2006-03-07 21:55:42 -08001007 dir, dentry->d_name.name, dentry, nameidata);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001008
Sripathi Kodi11e9b492010-03-29 18:13:59 -05001009 if (dentry->d_name.len > NAME_MAX)
1010 return ERR_PTR(-ENAMETOOLONG);
1011
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001012 sb = dir->i_sb;
1013 v9ses = v9fs_inode2v9ses(dir);
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +05301014 /* We can walk d_parent because we hold the dir->i_mutex */
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001015 dfid = v9fs_fid_lookup(dentry->d_parent);
1016 if (IS_ERR(dfid))
David Howellse231c2e2008-02-07 00:15:26 -08001017 return ERR_CAST(dfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001018
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001019 name = (char *) dentry->d_name.name;
1020 fid = p9_client_walk(dfid, 1, &name, 1);
1021 if (IS_ERR(fid)) {
1022 result = PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001023 if (result == -ENOENT) {
Aneesh Kumar K.V85e0df22010-05-14 13:04:39 +00001024 inode = NULL;
1025 goto inst_out;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001026 }
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001027
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001028 return ERR_PTR(result);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001029 }
1030
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001031 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1032 if (IS_ERR(inode)) {
1033 result = PTR_ERR(inode);
1034 inode = NULL;
1035 goto error;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001036 }
1037
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001038 result = v9fs_fid_add(dentry, fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001039 if (result < 0)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001040 goto error;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001041
Aneesh Kumar K.V85e0df22010-05-14 13:04:39 +00001042inst_out:
1043 if (v9ses->cache)
Eric Van Hensbergene03abc02007-02-11 13:21:39 -06001044 dentry->d_op = &v9fs_cached_dentry_operations;
1045 else
1046 dentry->d_op = &v9fs_dentry_operations;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001047
1048 d_add(dentry, inode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001049 return NULL;
1050
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001051error:
Julien Brunel62aa5282008-09-24 16:22:22 -05001052 p9_client_clunk(fid);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001053
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001054 return ERR_PTR(result);
1055}
1056
1057/**
1058 * v9fs_vfs_unlink - VFS unlink hook to delete an inode
1059 * @i: inode that is being unlinked
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001060 * @d: dentry that is being unlinked
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001061 *
1062 */
1063
1064static int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
1065{
1066 return v9fs_remove(i, d, 0);
1067}
1068
1069/**
1070 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
1071 * @i: inode that is being unlinked
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001072 * @d: dentry that is being unlinked
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001073 *
1074 */
1075
1076static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
1077{
1078 return v9fs_remove(i, d, 1);
1079}
1080
1081/**
1082 * v9fs_vfs_rename - VFS hook to rename an inode
1083 * @old_dir: old dir inode
1084 * @old_dentry: old dentry
1085 * @new_dir: new dir inode
1086 * @new_dentry: new dentry
1087 *
1088 */
1089
1090static int
1091v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1092 struct inode *new_dir, struct dentry *new_dentry)
1093{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001094 struct inode *old_inode;
1095 struct v9fs_session_info *v9ses;
1096 struct p9_fid *oldfid;
1097 struct p9_fid *olddirfid;
1098 struct p9_fid *newdirfid;
1099 struct p9_wstat wstat;
1100 int retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001101
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001102 P9_DPRINTK(P9_DEBUG_VFS, "\n");
1103 retval = 0;
1104 old_inode = old_dentry->d_inode;
1105 v9ses = v9fs_inode2v9ses(old_inode);
1106 oldfid = v9fs_fid_lookup(old_dentry);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001107 if (IS_ERR(oldfid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001108 return PTR_ERR(oldfid);
1109
1110 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001111 if (IS_ERR(olddirfid)) {
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001112 retval = PTR_ERR(olddirfid);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001113 goto done;
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001114 }
1115
1116 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001117 if (IS_ERR(newdirfid)) {
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001118 retval = PTR_ERR(newdirfid);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001119 goto clunk_olddir;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001120 }
1121
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +05301122 down_write(&v9ses->rename_sem);
Sripathi Kodi4681dbd2010-03-25 12:47:26 +00001123 if (v9fs_proto_dotl(v9ses)) {
1124 retval = p9_client_rename(oldfid, newdirfid,
1125 (char *) new_dentry->d_name.name);
1126 if (retval != -ENOSYS)
1127 goto clunk_newdir;
1128 }
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +05301129 if (old_dentry->d_parent != new_dentry->d_parent) {
1130 /*
1131 * 9P .u can only handle file rename in the same directory
1132 */
Sripathi Kodi4681dbd2010-03-25 12:47:26 +00001133
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001134 P9_DPRINTK(P9_DEBUG_ERROR,
1135 "old dir and new dir are different\n");
Eric Van Hensbergen621997c2007-01-26 00:57:04 -08001136 retval = -EXDEV;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001137 goto clunk_newdir;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001138 }
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001139 v9fs_blank_wstat(&wstat);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001140 wstat.muid = v9ses->uname;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001141 wstat.name = (char *) new_dentry->d_name.name;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001142 retval = p9_client_wstat(oldfid, &wstat);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001143
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001144clunk_newdir:
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +05301145 if (!retval)
1146 /* successful rename */
1147 d_move(old_dentry, new_dentry);
1148 up_write(&v9ses->rename_sem);
Latchesar Ionkov22150c42007-10-23 13:48:33 -05001149 p9_client_clunk(newdirfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001150
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001151clunk_olddir:
Latchesar Ionkov22150c42007-10-23 13:48:33 -05001152 p9_client_clunk(olddirfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001153
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001154done:
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001155 return retval;
1156}
1157
1158/**
Adrian Bunk943ffb52006-01-10 00:10:13 +01001159 * v9fs_vfs_getattr - retrieve file metadata
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001160 * @mnt: mount information
1161 * @dentry: file to get attributes on
1162 * @stat: metadata structure to populate
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001163 *
1164 */
1165
1166static int
1167v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1168 struct kstat *stat)
1169{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001170 int err;
1171 struct v9fs_session_info *v9ses;
1172 struct p9_fid *fid;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001173 struct p9_wstat *st;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001174
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001175 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1176 err = -EPERM;
1177 v9ses = v9fs_inode2v9ses(dentry->d_inode);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -05001178 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
Eric Van Hensbergen9523a842007-07-13 13:01:27 -05001179 return simple_getattr(mnt, dentry, stat);
1180
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001181 fid = v9fs_fid_lookup(dentry);
1182 if (IS_ERR(fid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001183 return PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001184
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001185 st = p9_client_stat(fid);
1186 if (IS_ERR(st))
1187 return PTR_ERR(st);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001188
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001189 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001190 generic_fillattr(dentry->d_inode, stat);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001191
Latchesar Ionkov62b2be52010-08-24 18:13:59 +00001192 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001193 kfree(st);
1194 return 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001195}
1196
Sripathi Kodif0853122010-07-12 20:07:23 +05301197static int
1198v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
1199 struct kstat *stat)
1200{
1201 int err;
1202 struct v9fs_session_info *v9ses;
1203 struct p9_fid *fid;
1204 struct p9_stat_dotl *st;
1205
1206 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1207 err = -EPERM;
1208 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1209 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
1210 return simple_getattr(mnt, dentry, stat);
1211
1212 fid = v9fs_fid_lookup(dentry);
1213 if (IS_ERR(fid))
1214 return PTR_ERR(fid);
1215
1216 /* Ask for all the fields in stat structure. Server will return
1217 * whatever it supports
1218 */
1219
1220 st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
1221 if (IS_ERR(st))
1222 return PTR_ERR(st);
1223
1224 v9fs_stat2inode_dotl(st, dentry->d_inode);
1225 generic_fillattr(dentry->d_inode, stat);
1226 /* Change block size to what the server returned */
1227 stat->blksize = st->st_blksize;
1228
1229 kfree(st);
1230 return 0;
1231}
1232
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001233/**
1234 * v9fs_vfs_setattr - set file metadata
1235 * @dentry: file whose metadata to set
1236 * @iattr: metadata assignment structure
1237 *
1238 */
1239
1240static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1241{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001242 int retval;
1243 struct v9fs_session_info *v9ses;
1244 struct p9_fid *fid;
1245 struct p9_wstat wstat;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001246
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001247 P9_DPRINTK(P9_DEBUG_VFS, "\n");
1248 retval = -EPERM;
1249 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1250 fid = v9fs_fid_lookup(dentry);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001251 if(IS_ERR(fid))
1252 return PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001253
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001254 v9fs_blank_wstat(&wstat);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001255 if (iattr->ia_valid & ATTR_MODE)
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001256 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001257
1258 if (iattr->ia_valid & ATTR_MTIME)
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001259 wstat.mtime = iattr->ia_mtime.tv_sec;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001260
1261 if (iattr->ia_valid & ATTR_ATIME)
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001262 wstat.atime = iattr->ia_atime.tv_sec;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001263
1264 if (iattr->ia_valid & ATTR_SIZE)
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001265 wstat.length = iattr->ia_size;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001266
Sripathi Kodidd6102f2010-03-05 18:48:00 +00001267 if (v9fs_proto_dotu(v9ses)) {
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001268 if (iattr->ia_valid & ATTR_UID)
1269 wstat.n_uid = iattr->ia_uid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001270
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001271 if (iattr->ia_valid & ATTR_GID)
1272 wstat.n_gid = iattr->ia_gid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001273 }
1274
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001275 retval = p9_client_wstat(fid, &wstat);
Christoph Hellwig10257742010-06-04 11:30:02 +02001276 if (retval < 0)
1277 return retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001278
Christoph Hellwig10257742010-06-04 11:30:02 +02001279 if ((iattr->ia_valid & ATTR_SIZE) &&
1280 iattr->ia_size != i_size_read(dentry->d_inode)) {
1281 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
1282 if (retval)
1283 return retval;
1284 }
1285
1286 setattr_copy(dentry->d_inode, iattr);
1287 mark_inode_dirty(dentry->d_inode);
1288 return 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001289}
1290
1291/**
Sripathi Kodi87d78452010-06-18 11:50:10 +05301292 * v9fs_vfs_setattr_dotl - set file metadata
1293 * @dentry: file whose metadata to set
1294 * @iattr: metadata assignment structure
1295 *
1296 */
1297
Aneesh Kumar K.V22d8dcd2010-09-28 00:27:40 +05301298int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
Sripathi Kodi87d78452010-06-18 11:50:10 +05301299{
1300 int retval;
1301 struct v9fs_session_info *v9ses;
1302 struct p9_fid *fid;
1303 struct p9_iattr_dotl p9attr;
1304
1305 P9_DPRINTK(P9_DEBUG_VFS, "\n");
1306
1307 retval = inode_change_ok(dentry->d_inode, iattr);
1308 if (retval)
1309 return retval;
1310
1311 p9attr.valid = iattr->ia_valid;
1312 p9attr.mode = iattr->ia_mode;
1313 p9attr.uid = iattr->ia_uid;
1314 p9attr.gid = iattr->ia_gid;
1315 p9attr.size = iattr->ia_size;
1316 p9attr.atime_sec = iattr->ia_atime.tv_sec;
1317 p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
1318 p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
1319 p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
1320
1321 retval = -EPERM;
1322 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1323 fid = v9fs_fid_lookup(dentry);
1324 if (IS_ERR(fid))
1325 return PTR_ERR(fid);
1326
1327 retval = p9_client_setattr(fid, &p9attr);
Stephen Rothwell8cef9c62010-06-22 11:15:01 +10001328 if (retval < 0)
1329 return retval;
Sripathi Kodi87d78452010-06-18 11:50:10 +05301330
Stephen Rothwell8cef9c62010-06-22 11:15:01 +10001331 if ((iattr->ia_valid & ATTR_SIZE) &&
1332 iattr->ia_size != i_size_read(dentry->d_inode)) {
1333 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
1334 if (retval)
1335 return retval;
1336 }
1337
1338 setattr_copy(dentry->d_inode, iattr);
1339 mark_inode_dirty(dentry->d_inode);
Aneesh Kumar K.V6e8dc552010-09-28 00:27:40 +05301340 if (iattr->ia_valid & ATTR_MODE) {
1341 /* We also want to update ACL when we update mode bits */
1342 retval = v9fs_acl_chmod(dentry);
1343 if (retval < 0)
1344 return retval;
1345 }
Stephen Rothwell8cef9c62010-06-22 11:15:01 +10001346 return 0;
Sripathi Kodi87d78452010-06-18 11:50:10 +05301347}
1348
1349/**
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001350 * v9fs_stat2inode - populate an inode structure with mistat info
1351 * @stat: Plan 9 metadata (mistat) structure
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001352 * @inode: inode to populate
1353 * @sb: superblock of filesystem
1354 *
1355 */
1356
1357void
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001358v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001359 struct super_block *sb)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001360{
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001361 char ext[32];
Aneesh Kumar K.V57171442010-03-05 14:43:43 -06001362 char tag_name[14];
1363 unsigned int i_nlink;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001364 struct v9fs_session_info *v9ses = sb->s_fs_info;
1365
1366 inode->i_nlink = 1;
1367
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001368 inode->i_atime.tv_sec = stat->atime;
1369 inode->i_mtime.tv_sec = stat->mtime;
1370 inode->i_ctime.tv_sec = stat->mtime;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001371
Latchesar Ionkovbd32b822007-10-17 14:31:07 -05001372 inode->i_uid = v9ses->dfltuid;
1373 inode->i_gid = v9ses->dfltgid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001374
Sripathi Kodidd6102f2010-03-05 18:48:00 +00001375 if (v9fs_proto_dotu(v9ses)) {
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001376 inode->i_uid = stat->n_uid;
1377 inode->i_gid = stat->n_gid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001378 }
Aneesh Kumar K.V57171442010-03-05 14:43:43 -06001379 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1380 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1381 /*
1382 * Hadlink support got added later to
1383 * to the .u extension. So there can be
1384 * server out there that doesn't support
1385 * this even with .u extension. So check
1386 * for non NULL stat->extension
1387 */
1388 strncpy(ext, stat->extension, sizeof(ext));
1389 /* HARDLINKCOUNT %u */
1390 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1391 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1392 inode->i_nlink = i_nlink;
1393 }
1394 }
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001395 inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001396 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
1397 char type = 0;
1398 int major = -1;
1399 int minor = -1;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001400
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001401 strncpy(ext, stat->extension, sizeof(ext));
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001402 sscanf(ext, "%c %u %u", &type, &major, &minor);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001403 switch (type) {
1404 case 'c':
1405 inode->i_mode &= ~S_IFBLK;
1406 inode->i_mode |= S_IFCHR;
1407 break;
1408 case 'b':
1409 break;
1410 default:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001411 P9_DPRINTK(P9_DEBUG_ERROR,
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001412 "Unknown special type %c %s\n", type,
1413 stat->extension);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001414 };
1415 inode->i_rdev = MKDEV(major, minor);
Magnus Deininger57c7b4e2008-10-17 12:44:46 -05001416 init_special_inode(inode, inode->i_mode, inode->i_rdev);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001417 } else
1418 inode->i_rdev = 0;
1419
Abhishek Kulkarni7549ae32009-09-22 11:34:05 -05001420 i_size_write(inode, stat->length);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001421
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001422 /* not real number of blocks, but 512 byte ones ... */
Abhishek Kulkarni7549ae32009-09-22 11:34:05 -05001423 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001424}
1425
1426/**
Sripathi Kodif0853122010-07-12 20:07:23 +05301427 * v9fs_stat2inode_dotl - populate an inode structure with stat info
1428 * @stat: stat structure
1429 * @inode: inode to populate
1430 * @sb: superblock of filesystem
1431 *
1432 */
1433
1434void
1435v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
1436{
1437
1438 if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
1439 inode->i_atime.tv_sec = stat->st_atime_sec;
1440 inode->i_atime.tv_nsec = stat->st_atime_nsec;
1441 inode->i_mtime.tv_sec = stat->st_mtime_sec;
1442 inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
1443 inode->i_ctime.tv_sec = stat->st_ctime_sec;
1444 inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
1445 inode->i_uid = stat->st_uid;
1446 inode->i_gid = stat->st_gid;
1447 inode->i_nlink = stat->st_nlink;
1448 inode->i_mode = stat->st_mode;
1449 inode->i_rdev = new_decode_dev(stat->st_rdev);
1450
1451 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode)))
1452 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1453
1454 i_size_write(inode, stat->st_size);
1455 inode->i_blocks = stat->st_blocks;
1456 } else {
1457 if (stat->st_result_mask & P9_STATS_ATIME) {
1458 inode->i_atime.tv_sec = stat->st_atime_sec;
1459 inode->i_atime.tv_nsec = stat->st_atime_nsec;
1460 }
1461 if (stat->st_result_mask & P9_STATS_MTIME) {
1462 inode->i_mtime.tv_sec = stat->st_mtime_sec;
1463 inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
1464 }
1465 if (stat->st_result_mask & P9_STATS_CTIME) {
1466 inode->i_ctime.tv_sec = stat->st_ctime_sec;
1467 inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
1468 }
1469 if (stat->st_result_mask & P9_STATS_UID)
1470 inode->i_uid = stat->st_uid;
1471 if (stat->st_result_mask & P9_STATS_GID)
1472 inode->i_gid = stat->st_gid;
1473 if (stat->st_result_mask & P9_STATS_NLINK)
1474 inode->i_nlink = stat->st_nlink;
1475 if (stat->st_result_mask & P9_STATS_MODE) {
1476 inode->i_mode = stat->st_mode;
1477 if ((S_ISBLK(inode->i_mode)) ||
1478 (S_ISCHR(inode->i_mode)))
1479 init_special_inode(inode, inode->i_mode,
1480 inode->i_rdev);
1481 }
1482 if (stat->st_result_mask & P9_STATS_RDEV)
1483 inode->i_rdev = new_decode_dev(stat->st_rdev);
1484 if (stat->st_result_mask & P9_STATS_SIZE)
1485 i_size_write(inode, stat->st_size);
1486 if (stat->st_result_mask & P9_STATS_BLOCKS)
1487 inode->i_blocks = stat->st_blocks;
1488 }
1489 if (stat->st_result_mask & P9_STATS_GEN)
1490 inode->i_generation = stat->st_gen;
1491
1492 /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
1493 * because the inode structure does not have fields for them.
1494 */
1495}
1496
1497/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001498 * v9fs_qid2ino - convert qid into inode number
1499 * @qid: qid to hash
1500 *
1501 * BUG: potential for inode number collisions?
1502 */
1503
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001504ino_t v9fs_qid2ino(struct p9_qid *qid)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001505{
1506 u64 path = qid->path + 2;
1507 ino_t i = 0;
1508
1509 if (sizeof(ino_t) == sizeof(path))
1510 memcpy(&i, &path, sizeof(ino_t));
1511 else
1512 i = (ino_t) (path ^ (path >> 32));
1513
1514 return i;
1515}
1516
1517/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001518 * v9fs_readlink - read a symlink's location (internal version)
1519 * @dentry: dentry for symlink
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001520 * @buffer: buffer to load symlink location into
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001521 * @buflen: length of buffer
1522 *
1523 */
1524
1525static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1526{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001527 int retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001528
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001529 struct v9fs_session_info *v9ses;
1530 struct p9_fid *fid;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001531 struct p9_wstat *st;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001532
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001533 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1534 retval = -EPERM;
1535 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1536 fid = v9fs_fid_lookup(dentry);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001537 if (IS_ERR(fid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001538 return PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001539
M. Mohan Kumar329176c2010-09-28 19:59:25 +05301540 if (!v9fs_proto_dotu(v9ses))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001541 return -EBADF;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001542
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001543 st = p9_client_stat(fid);
1544 if (IS_ERR(st))
1545 return PTR_ERR(st);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001546
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001547 if (!(st->mode & P9_DMSYMLINK)) {
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001548 retval = -EINVAL;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001549 goto done;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001550 }
1551
1552 /* copy extension buffer into buffer */
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001553 strncpy(buffer, st->extension, buflen);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001554
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001555 P9_DPRINTK(P9_DEBUG_VFS,
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001556 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001557
Martin Stava2511cd02009-11-02 08:39:34 -06001558 retval = strnlen(buffer, buflen);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001559done:
Latchesar Ionkov62b2be52010-08-24 18:13:59 +00001560 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001561 kfree(st);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001562 return retval;
1563}
1564
1565/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001566 * v9fs_vfs_follow_link - follow a symlink path
1567 * @dentry: dentry for symlink
1568 * @nd: nameidata
1569 *
1570 */
1571
1572static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1573{
1574 int len = 0;
1575 char *link = __getname();
1576
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001577 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001578
1579 if (!link)
1580 link = ERR_PTR(-ENOMEM);
1581 else {
Latchesar Ionkov16cce6d2006-03-25 03:07:26 -08001582 len = v9fs_readlink(dentry, link, PATH_MAX);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001583
1584 if (len < 0) {
Davi Arnautce44eeb2005-11-07 00:59:36 -08001585 __putname(link);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001586 link = ERR_PTR(len);
1587 } else
Martin Stava2511cd02009-11-02 08:39:34 -06001588 link[min(len, PATH_MAX-1)] = 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001589 }
1590 nd_set_link(nd, link);
1591
1592 return NULL;
1593}
1594
1595/**
1596 * v9fs_vfs_put_link - release a symlink path
1597 * @dentry: dentry for symlink
1598 * @nd: nameidata
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001599 * @p: unused
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001600 *
1601 */
1602
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001603static void
1604v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001605{
1606 char *s = nd_get_link(nd);
1607
Duane Griffin6ff23202008-12-19 16:45:21 -06001608 P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
1609 IS_ERR(s) ? "<error>" : s);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001610 if (!IS_ERR(s))
Davi Arnautce44eeb2005-11-07 00:59:36 -08001611 __putname(s);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001612}
1613
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001614/**
1615 * v9fs_vfs_mkspecial - create a special file
1616 * @dir: inode to create special file in
1617 * @dentry: dentry to create
1618 * @mode: mode to create special file
1619 * @extension: 9p2000.u format extension string representing special file
1620 *
1621 */
1622
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001623static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1624 int mode, const char *extension)
1625{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001626 u32 perm;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001627 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001628 struct p9_fid *fid;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001629
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001630 v9ses = v9fs_inode2v9ses(dir);
Sripathi Kodidd6102f2010-03-05 18:48:00 +00001631 if (!v9fs_proto_dotu(v9ses)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001632 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001633 return -EPERM;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001634 }
1635
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001636 perm = unixmode2p9mode(v9ses, mode);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001637 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1638 P9_OREAD);
1639 if (IS_ERR(fid))
1640 return PTR_ERR(fid);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001641
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001642 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001643 return 0;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001644}
1645
1646/**
Venkateswararao Jujjuri (JV)50cc42f2010-06-09 15:59:31 -07001647 * v9fs_vfs_symlink_dotl - helper function to create symlinks
1648 * @dir: directory inode containing symlink
1649 * @dentry: dentry for symlink
1650 * @symname: symlink data
1651 *
1652 * See Also: 9P2000.L RFC for more information
1653 *
1654 */
1655
1656static int
1657v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
1658 const char *symname)
1659{
1660 struct v9fs_session_info *v9ses;
1661 struct p9_fid *dfid;
1662 struct p9_fid *fid = NULL;
1663 struct inode *inode;
1664 struct p9_qid qid;
1665 char *name;
1666 int err;
1667 gid_t gid;
1668
1669 name = (char *) dentry->d_name.name;
1670 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n",
1671 dir->i_ino, name, symname);
1672 v9ses = v9fs_inode2v9ses(dir);
1673
1674 dfid = v9fs_fid_lookup(dentry->d_parent);
1675 if (IS_ERR(dfid)) {
1676 err = PTR_ERR(dfid);
1677 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
1678 return err;
1679 }
1680
1681 gid = v9fs_get_fsgid_for_create(dir);
1682
Venkateswararao Jujjuri (JV)50cc42f2010-06-09 15:59:31 -07001683 /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */
1684 err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid);
1685
1686 if (err < 0) {
1687 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err);
1688 goto error;
1689 }
1690
1691 if (v9ses->cache) {
1692 /* Now walk from the parent so we can get an unopened fid. */
1693 fid = p9_client_walk(dfid, 1, &name, 1);
1694 if (IS_ERR(fid)) {
1695 err = PTR_ERR(fid);
1696 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
1697 err);
1698 fid = NULL;
1699 goto error;
1700 }
1701
1702 /* instantiate inode and assign the unopened fid to dentry */
1703 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1704 if (IS_ERR(inode)) {
1705 err = PTR_ERR(inode);
1706 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
1707 err);
1708 goto error;
1709 }
1710 dentry->d_op = &v9fs_cached_dentry_operations;
1711 d_instantiate(dentry, inode);
1712 err = v9fs_fid_add(dentry, fid);
1713 if (err < 0)
1714 goto error;
1715 fid = NULL;
1716 } else {
1717 /* Not in cached mode. No need to populate inode with stat */
1718 inode = v9fs_get_inode(dir->i_sb, S_IFLNK);
1719 if (IS_ERR(inode)) {
1720 err = PTR_ERR(inode);
1721 goto error;
1722 }
1723 dentry->d_op = &v9fs_dentry_operations;
1724 d_instantiate(dentry, inode);
1725 }
1726
1727error:
1728 if (fid)
1729 p9_client_clunk(fid);
1730
1731 return err;
1732}
1733
1734/**
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001735 * v9fs_vfs_symlink - helper function to create symlinks
1736 * @dir: directory inode containing symlink
1737 * @dentry: dentry for symlink
1738 * @symname: symlink data
1739 *
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001740 * See Also: 9P2000.u RFC for more information
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001741 *
1742 */
1743
1744static int
1745v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1746{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001747 P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
1748 dentry->d_name.name, symname);
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001749
1750 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
1751}
1752
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001753/**
1754 * v9fs_vfs_link - create a hardlink
1755 * @old_dentry: dentry for file to link to
1756 * @dir: inode destination for new link
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001757 * @dentry: dentry for link
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001758 *
1759 */
1760
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001761static int
1762v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1763 struct dentry *dentry)
1764{
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001765 int retval;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001766 struct p9_fid *oldfid;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001767 char *name;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001768
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001769 P9_DPRINTK(P9_DEBUG_VFS,
1770 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001771 old_dentry->d_name.name);
1772
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001773 oldfid = v9fs_fid_clone(old_dentry);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001774 if (IS_ERR(oldfid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001775 return PTR_ERR(oldfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001776
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001777 name = __getname();
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001778 if (unlikely(!name)) {
1779 retval = -ENOMEM;
1780 goto clunk_fid;
1781 }
Florin Malita0710d362006-06-25 05:48:31 -07001782
Latchesar Ionkov16cce6d2006-03-25 03:07:26 -08001783 sprintf(name, "%d\n", oldfid->fid);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001784 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001785 __putname(name);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001786
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001787clunk_fid:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001788 p9_client_clunk(oldfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001789 return retval;
1790}
1791
1792/**
Eric Van Hensbergen09d34ee2010-08-02 14:28:09 -05001793 * v9fs_vfs_link_dotl - create a hardlink for dotl
1794 * @old_dentry: dentry for file to link to
1795 * @dir: inode destination for new link
1796 * @dentry: dentry for link
1797 *
1798 */
1799
1800static int
1801v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
1802 struct dentry *dentry)
1803{
1804 int err;
1805 struct p9_fid *dfid, *oldfid;
1806 char *name;
1807 struct v9fs_session_info *v9ses;
1808 struct dentry *dir_dentry;
1809
1810 P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n",
1811 dir->i_ino, old_dentry->d_name.name,
1812 dentry->d_name.name);
1813
1814 v9ses = v9fs_inode2v9ses(dir);
1815 dir_dentry = v9fs_dentry_from_dir_inode(dir);
1816 dfid = v9fs_fid_lookup(dir_dentry);
1817 if (IS_ERR(dfid))
1818 return PTR_ERR(dfid);
1819
1820 oldfid = v9fs_fid_lookup(old_dentry);
1821 if (IS_ERR(oldfid))
1822 return PTR_ERR(oldfid);
1823
1824 name = (char *) dentry->d_name.name;
1825
1826 err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name);
1827
1828 if (err < 0) {
1829 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
1830 return err;
1831 }
1832
1833 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1834 /* Get the latest stat info from server. */
1835 struct p9_fid *fid;
1836 struct p9_stat_dotl *st;
1837
1838 fid = v9fs_fid_lookup(old_dentry);
1839 if (IS_ERR(fid))
1840 return PTR_ERR(fid);
1841
1842 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
1843 if (IS_ERR(st))
1844 return PTR_ERR(st);
1845
1846 v9fs_stat2inode_dotl(st, old_dentry->d_inode);
1847
1848 kfree(st);
1849 } else {
1850 /* Caching disabled. No need to get upto date stat info.
Al Viro7de9c6e2010-10-23 11:11:40 -04001851 * This dentry will be released immediately. So, just hold the
1852 * inode
Eric Van Hensbergen09d34ee2010-08-02 14:28:09 -05001853 */
Al Viro7de9c6e2010-10-23 11:11:40 -04001854 ihold(old_dentry->d_inode);
Eric Van Hensbergen09d34ee2010-08-02 14:28:09 -05001855 }
1856
1857 dentry->d_op = old_dentry->d_op;
1858 d_instantiate(dentry, old_dentry->d_inode);
1859
1860 return err;
1861}
1862
1863/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001864 * v9fs_vfs_mknod - create a special file
1865 * @dir: inode destination for new link
1866 * @dentry: dentry for file
1867 * @mode: mode for creation
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001868 * @rdev: device associated with special file
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001869 *
1870 */
1871
1872static int
1873v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1874{
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001875 int retval;
1876 char *name;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001877
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001878 P9_DPRINTK(P9_DEBUG_VFS,
1879 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001880 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1881
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001882 if (!new_valid_dev(rdev))
1883 return -EINVAL;
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001884
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001885 name = __getname();
Eugene Teoc0291a02006-03-25 03:07:27 -08001886 if (!name)
1887 return -ENOMEM;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001888 /* build extension */
1889 if (S_ISBLK(mode))
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001890 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001891 else if (S_ISCHR(mode))
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001892 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001893 else if (S_ISFIFO(mode))
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001894 *name = 0;
Venkateswararao Jujjuri75cc5c92010-05-22 12:20:30 -05001895 else if (S_ISSOCK(mode))
1896 *name = 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001897 else {
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001898 __putname(name);
1899 return -EINVAL;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001900 }
1901
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001902 retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
1903 __putname(name);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001904
1905 return retval;
1906}
1907
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301908/**
1909 * v9fs_vfs_mknod_dotl - create a special file
1910 * @dir: inode destination for new link
1911 * @dentry: dentry for file
1912 * @mode: mode for creation
1913 * @rdev: device associated with special file
1914 *
1915 */
1916static int
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +05301917v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301918 dev_t rdev)
1919{
1920 int err;
1921 char *name;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +05301922 mode_t mode;
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301923 struct v9fs_session_info *v9ses;
1924 struct p9_fid *fid = NULL, *dfid = NULL;
1925 struct inode *inode;
1926 gid_t gid;
1927 struct p9_qid qid;
M. Mohan Kumar01a622b2010-06-16 14:27:22 +05301928 struct dentry *dir_dentry;
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +05301929 struct posix_acl *dacl = NULL, *pacl = NULL;
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301930
1931 P9_DPRINTK(P9_DEBUG_VFS,
1932 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +05301933 dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev));
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301934
1935 if (!new_valid_dev(rdev))
1936 return -EINVAL;
1937
1938 v9ses = v9fs_inode2v9ses(dir);
1939 dir_dentry = v9fs_dentry_from_dir_inode(dir);
M. Mohan Kumar01a622b2010-06-16 14:27:22 +05301940 dfid = v9fs_fid_lookup(dir_dentry);
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301941 if (IS_ERR(dfid)) {
1942 err = PTR_ERR(dfid);
1943 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
1944 dfid = NULL;
1945 goto error;
1946 }
1947
1948 gid = v9fs_get_fsgid_for_create(dir);
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +05301949 mode = omode;
1950 /* Update mode based on ACL value */
1951 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
1952 if (err) {
1953 P9_DPRINTK(P9_DEBUG_VFS,
1954 "Failed to get acl values in mknod %d\n", err);
1955 goto error;
1956 }
M. Mohan Kumar4b435162010-06-16 14:27:01 +05301957 name = (char *) dentry->d_name.name;
1958
1959 err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
1960 if (err < 0)
1961 goto error;
1962
1963 /* instantiate inode and assign the unopened fid to the dentry */
1964 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1965 fid = p9_client_walk(dfid, 1, &name, 1);
1966 if (IS_ERR(fid)) {
1967 err = PTR_ERR(fid);
1968 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
1969 err);
1970 fid = NULL;
1971 goto error;
1972 }
1973
1974 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1975 if (IS_ERR(inode)) {
1976 err = PTR_ERR(inode);
1977 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
1978 err);
1979 goto error;
1980 }
1981 dentry->d_op = &v9fs_cached_dentry_operations;
1982 d_instantiate(dentry, inode);
1983 err = v9fs_fid_add(dentry, fid);
1984 if (err < 0)
1985 goto error;
1986 fid = NULL;
1987 } else {
1988 /*
1989 * Not in cached mode. No need to populate inode with stat.
1990 * socket syscall returns a fd, so we need instantiate
1991 */
1992 inode = v9fs_get_inode(dir->i_sb, mode);
1993 if (IS_ERR(inode)) {
1994 err = PTR_ERR(inode);
1995 goto error;
1996 }
1997 dentry->d_op = &v9fs_dentry_operations;
1998 d_instantiate(dentry, inode);
1999 }
Aneesh Kumar K.Vad77dbc2010-09-28 00:27:40 +05302000 /* Now set the ACL based on the default value */
2001 v9fs_set_create_acl(dentry, dacl, pacl);
M. Mohan Kumar4b435162010-06-16 14:27:01 +05302002error:
2003 if (fid)
2004 p9_client_clunk(fid);
2005 return err;
2006}
2007
M. Mohan Kumar329176c2010-09-28 19:59:25 +05302008static int
2009v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen)
2010{
2011 int retval;
2012 struct p9_fid *fid;
2013 char *target = NULL;
2014
2015 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
2016 retval = -EPERM;
2017 fid = v9fs_fid_lookup(dentry);
2018 if (IS_ERR(fid))
2019 return PTR_ERR(fid);
2020
2021 retval = p9_client_readlink(fid, &target);
2022 if (retval < 0)
2023 return retval;
2024
2025 strncpy(buffer, target, buflen);
2026 P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer);
2027
2028 retval = strnlen(buffer, buflen);
2029 return retval;
2030}
2031
2032/**
2033 * v9fs_vfs_follow_link_dotl - follow a symlink path
2034 * @dentry: dentry for symlink
2035 * @nd: nameidata
2036 *
2037 */
2038
2039static void *
2040v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
2041{
2042 int len = 0;
2043 char *link = __getname();
2044
2045 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
2046
2047 if (!link)
2048 link = ERR_PTR(-ENOMEM);
2049 else {
2050 len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX);
2051 if (len < 0) {
2052 __putname(link);
2053 link = ERR_PTR(len);
2054 } else
2055 link[min(len, PATH_MAX-1)] = 0;
2056 }
2057 nd_set_link(nd, link);
2058
2059 return NULL;
2060}
2061
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002062static const struct inode_operations v9fs_dir_inode_operations_dotu = {
2063 .create = v9fs_vfs_create,
2064 .lookup = v9fs_vfs_lookup,
2065 .symlink = v9fs_vfs_symlink,
Venkateswararao Jujjuri (JV)50cc42f2010-06-09 15:59:31 -07002066 .link = v9fs_vfs_link,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002067 .unlink = v9fs_vfs_unlink,
2068 .mkdir = v9fs_vfs_mkdir,
2069 .rmdir = v9fs_vfs_rmdir,
Aneesh Kumar K.V1d76e312010-08-30 17:43:07 +00002070 .mknod = v9fs_vfs_mknod,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002071 .rename = v9fs_vfs_rename,
2072 .getattr = v9fs_vfs_getattr,
2073 .setattr = v9fs_vfs_setattr,
2074};
2075
2076static const struct inode_operations v9fs_dir_inode_operations_dotl = {
Venkateswararao Jujjuri (JV)56431352010-06-17 18:27:46 -07002077 .create = v9fs_vfs_create_dotl,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002078 .lookup = v9fs_vfs_lookup,
Venkateswararao Jujjuri (JV)50cc42f2010-06-09 15:59:31 -07002079 .link = v9fs_vfs_link_dotl,
2080 .symlink = v9fs_vfs_symlink_dotl,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002081 .unlink = v9fs_vfs_unlink,
M. Mohan Kumar01a622b2010-06-16 14:27:22 +05302082 .mkdir = v9fs_vfs_mkdir_dotl,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002083 .rmdir = v9fs_vfs_rmdir,
M. Mohan Kumar4b435162010-06-16 14:27:01 +05302084 .mknod = v9fs_vfs_mknod_dotl,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002085 .rename = v9fs_vfs_rename,
Sripathi Kodif0853122010-07-12 20:07:23 +05302086 .getattr = v9fs_vfs_getattr_dotl,
Sripathi Kodi87d78452010-06-18 11:50:10 +05302087 .setattr = v9fs_vfs_setattr_dotl,
Aneesh Kumar K.Vebf46262010-05-31 13:22:56 +05302088 .setxattr = generic_setxattr,
2089 .getxattr = generic_getxattr,
2090 .removexattr = generic_removexattr,
2091 .listxattr = v9fs_listxattr,
Aneesh Kumar K.V85ff8722010-09-28 00:27:39 +05302092 .check_acl = v9fs_check_acl,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002093};
2094
Arjan van de Ven754661f2007-02-12 00:55:38 -08002095static const struct inode_operations v9fs_dir_inode_operations = {
Eric Van Hensbergenb5016112005-09-09 13:04:27 -07002096 .create = v9fs_vfs_create,
2097 .lookup = v9fs_vfs_lookup,
2098 .unlink = v9fs_vfs_unlink,
2099 .mkdir = v9fs_vfs_mkdir,
2100 .rmdir = v9fs_vfs_rmdir,
2101 .mknod = v9fs_vfs_mknod,
2102 .rename = v9fs_vfs_rename,
2103 .getattr = v9fs_vfs_getattr,
2104 .setattr = v9fs_vfs_setattr,
2105};
2106
Arjan van de Ven754661f2007-02-12 00:55:38 -08002107static const struct inode_operations v9fs_file_inode_operations = {
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002108 .getattr = v9fs_vfs_getattr,
2109 .setattr = v9fs_vfs_setattr,
2110};
2111
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002112static const struct inode_operations v9fs_file_inode_operations_dotl = {
Sripathi Kodif0853122010-07-12 20:07:23 +05302113 .getattr = v9fs_vfs_getattr_dotl,
Sripathi Kodi87d78452010-06-18 11:50:10 +05302114 .setattr = v9fs_vfs_setattr_dotl,
Aneesh Kumar K.Vebf46262010-05-31 13:22:56 +05302115 .setxattr = generic_setxattr,
2116 .getxattr = generic_getxattr,
2117 .removexattr = generic_removexattr,
2118 .listxattr = v9fs_listxattr,
Aneesh Kumar K.V85ff8722010-09-28 00:27:39 +05302119 .check_acl = v9fs_check_acl,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002120};
2121
Arjan van de Ven754661f2007-02-12 00:55:38 -08002122static const struct inode_operations v9fs_symlink_inode_operations = {
Al Viro204f2f02009-12-23 00:35:54 -05002123 .readlink = generic_readlink,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07002124 .follow_link = v9fs_vfs_follow_link,
2125 .put_link = v9fs_vfs_put_link,
2126 .getattr = v9fs_vfs_getattr,
2127 .setattr = v9fs_vfs_setattr,
2128};
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002129
2130static const struct inode_operations v9fs_symlink_inode_operations_dotl = {
M. Mohan Kumar329176c2010-09-28 19:59:25 +05302131 .readlink = v9fs_vfs_readlink_dotl,
2132 .follow_link = v9fs_vfs_follow_link_dotl,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002133 .put_link = v9fs_vfs_put_link,
Sripathi Kodif0853122010-07-12 20:07:23 +05302134 .getattr = v9fs_vfs_getattr_dotl,
Sripathi Kodi87d78452010-06-18 11:50:10 +05302135 .setattr = v9fs_vfs_setattr_dotl,
Aneesh Kumar K.Vebf46262010-05-31 13:22:56 +05302136 .setxattr = generic_setxattr,
2137 .getxattr = generic_getxattr,
2138 .removexattr = generic_removexattr,
2139 .listxattr = v9fs_listxattr,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00002140};