blob: 83af2b7e65db25dfa39ea9d3abc1effe0c4318ec [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;
Arjan van de Ven754661f2007-02-12 00:55:38 -080052static const struct inode_operations v9fs_file_inode_operations;
53static const struct inode_operations v9fs_symlink_inode_operations;
Aneesh Kumar K.Vf5fc6142010-10-12 13:02:25 +053054
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070055/**
56 * unixmode2p9mode - convert unix mode bits to plan 9
57 * @v9ses: v9fs session information
58 * @mode: mode to convert
59 *
60 */
61
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -070062static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070063{
64 int res;
65 res = mode & 0777;
66 if (S_ISDIR(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050067 res |= P9_DMDIR;
Sripathi Kodidd6102f2010-03-05 18:48:00 +000068 if (v9fs_proto_dotu(v9ses)) {
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070069 if (S_ISLNK(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050070 res |= P9_DMSYMLINK;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070071 if (v9ses->nodev == 0) {
72 if (S_ISSOCK(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050073 res |= P9_DMSOCKET;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070074 if (S_ISFIFO(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050075 res |= P9_DMNAMEDPIPE;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070076 if (S_ISBLK(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050077 res |= P9_DMDEVICE;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070078 if (S_ISCHR(mode))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050079 res |= P9_DMDEVICE;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070080 }
81
82 if ((mode & S_ISUID) == S_ISUID)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050083 res |= P9_DMSETUID;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070084 if ((mode & S_ISGID) == S_ISGID)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050085 res |= P9_DMSETGID;
Anthony Liguorid199d652008-02-06 19:25:06 -060086 if ((mode & S_ISVTX) == S_ISVTX)
87 res |= P9_DMSETVTX;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -050088 if ((mode & P9_DMLINK))
89 res |= P9_DMLINK;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -070090 }
91
92 return res;
93}
94
95/**
96 * p9mode2unixmode- convert plan9 mode bits to unix mode bits
97 * @v9ses: v9fs session information
98 * @mode: mode to convert
99 *
100 */
101
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -0700102static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700103{
104 int res;
105
106 res = mode & 0777;
107
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500108 if ((mode & P9_DMDIR) == P9_DMDIR)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700109 res |= S_IFDIR;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000110 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700111 res |= S_IFLNK;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000112 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700113 && (v9ses->nodev == 0))
114 res |= S_IFSOCK;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000115 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700116 && (v9ses->nodev == 0))
117 res |= S_IFIFO;
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000118 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700119 && (v9ses->nodev == 0))
120 res |= S_IFBLK;
121 else
122 res |= S_IFREG;
123
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000124 if (v9fs_proto_dotu(v9ses)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500125 if ((mode & P9_DMSETUID) == P9_DMSETUID)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700126 res |= S_ISUID;
127
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500128 if ((mode & P9_DMSETGID) == P9_DMSETGID)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700129 res |= S_ISGID;
Anthony Liguorid199d652008-02-06 19:25:06 -0600130
131 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
132 res |= S_ISVTX;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700133 }
134
135 return res;
136}
137
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600138/**
139 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
140 * @uflags: flags to convert
Eric Van Hensbergen2e4bef42008-06-24 17:39:39 -0500141 * @extended: if .u extensions are active
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600142 */
143
Eric Van Hensbergen2e4bef42008-06-24 17:39:39 -0500144int v9fs_uflags2omode(int uflags, int extended)
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800145{
146 int ret;
147
148 ret = 0;
149 switch (uflags&3) {
150 default:
151 case O_RDONLY:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500152 ret = P9_OREAD;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800153 break;
154
155 case O_WRONLY:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500156 ret = P9_OWRITE;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800157 break;
158
159 case O_RDWR:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500160 ret = P9_ORDWR;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800161 break;
162 }
163
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800164 if (uflags & O_TRUNC)
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500165 ret |= P9_OTRUNC;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800166
Eric Van Hensbergen2e4bef42008-06-24 17:39:39 -0500167 if (extended) {
168 if (uflags & O_EXCL)
169 ret |= P9_OEXCL;
170
171 if (uflags & O_APPEND)
172 ret |= P9_OAPPEND;
173 }
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800174
175 return ret;
176}
177
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700178/**
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800179 * v9fs_blank_wstat - helper function to setup a 9P stat structure
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800180 * @wstat: structure to initialize
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700181 *
182 */
183
M. Mohan Kumar7a4439c2010-02-08 15:36:48 -0600184void
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500185v9fs_blank_wstat(struct p9_wstat *wstat)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700186{
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800187 wstat->type = ~0;
188 wstat->dev = ~0;
189 wstat->qid.type = ~0;
190 wstat->qid.version = ~0;
191 *((long long *)&wstat->qid.path) = ~0;
192 wstat->mode = ~0;
193 wstat->atime = ~0;
194 wstat->mtime = ~0;
195 wstat->length = ~0;
196 wstat->name = NULL;
197 wstat->uid = NULL;
198 wstat->gid = NULL;
199 wstat->muid = NULL;
200 wstat->n_uid = ~0;
201 wstat->n_gid = ~0;
202 wstat->n_muid = ~0;
203 wstat->extension = NULL;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700204}
205
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500206#ifdef CONFIG_9P_FSCACHE
207/**
208 * v9fs_alloc_inode - helper function to allocate an inode
209 * This callback is executed before setting up the inode so that we
210 * can associate a vcookie with each inode.
211 *
212 */
213
214struct inode *v9fs_alloc_inode(struct super_block *sb)
215{
216 struct v9fs_cookie *vcookie;
217 vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
218 GFP_KERNEL);
219 if (!vcookie)
220 return NULL;
221
222 vcookie->fscache = NULL;
223 vcookie->qid = NULL;
224 spin_lock_init(&vcookie->lock);
225 return &vcookie->inode;
226}
227
228/**
229 * v9fs_destroy_inode - destroy an inode
230 *
231 */
232
Nick Pigginfa0d7e32011-01-07 17:49:49 +1100233static void v9fs_i_callback(struct rcu_head *head)
234{
235 struct inode *inode = container_of(head, struct inode, i_rcu);
236 INIT_LIST_HEAD(&inode->i_dentry);
237 kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
238}
239
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500240void v9fs_destroy_inode(struct inode *inode)
241{
Nick Pigginfa0d7e32011-01-07 17:49:49 +1100242 call_rcu(&inode->i_rcu, v9fs_i_callback);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500243}
244#endif
245
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700246/**
247 * v9fs_get_inode - helper function to setup an inode
248 * @sb: superblock
249 * @mode: mode to setup inode with
250 *
251 */
252
253struct inode *v9fs_get_inode(struct super_block *sb, int mode)
254{
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600255 int err;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800256 struct inode *inode;
Eric Van Hensbergenb5016112005-09-09 13:04:27 -0700257 struct v9fs_session_info *v9ses = sb->s_fs_info;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700258
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500259 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700260
261 inode = new_inode(sb);
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600262 if (!inode) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500263 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
Abhishek Kulkarni48559b4c2009-08-17 16:32:18 -0500264 return ERR_PTR(-ENOMEM);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700265 }
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600266
Dmitry Monakhov217f2062010-03-04 17:30:57 +0300267 inode_init_owner(inode, NULL, mode);
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600268 inode->i_blocks = 0;
269 inode->i_rdev = 0;
270 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
271 inode->i_mapping->a_ops = &v9fs_addr_operations;
272
273 switch (mode & S_IFMT) {
274 case S_IFIFO:
275 case S_IFBLK:
276 case S_IFCHR:
277 case S_IFSOCK:
M. Mohan Kumar4b435162010-06-16 14:27:01 +0530278 if (v9fs_proto_dotl(v9ses)) {
279 inode->i_op = &v9fs_file_inode_operations_dotl;
280 inode->i_fop = &v9fs_file_operations_dotl;
281 } else if (v9fs_proto_dotu(v9ses)) {
282 inode->i_op = &v9fs_file_inode_operations;
283 inode->i_fop = &v9fs_file_operations;
284 } else {
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600285 P9_DPRINTK(P9_DEBUG_ERROR,
286 "special files without extended mode\n");
287 err = -EINVAL;
288 goto error;
289 }
290 init_special_inode(inode, inode->i_mode, inode->i_rdev);
291 break;
292 case S_IFREG:
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000293 if (v9fs_proto_dotl(v9ses)) {
294 inode->i_op = &v9fs_file_inode_operations_dotl;
Aneesh Kumar K.V29236f42011-02-28 17:03:54 +0530295 if (v9ses->cache)
296 inode->i_fop =
297 &v9fs_cached_file_operations_dotl;
298 else
299 inode->i_fop = &v9fs_file_operations_dotl;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000300 } else {
301 inode->i_op = &v9fs_file_inode_operations;
Aneesh Kumar K.V29236f42011-02-28 17:03:54 +0530302 if (v9ses->cache)
303 inode->i_fop = &v9fs_cached_file_operations;
304 else
305 inode->i_fop = &v9fs_file_operations;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000306 }
307
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600308 break;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000309
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600310 case S_IFLNK:
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000311 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
312 P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with "
313 "legacy protocol.\n");
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600314 err = -EINVAL;
315 goto error;
316 }
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000317
318 if (v9fs_proto_dotl(v9ses))
319 inode->i_op = &v9fs_symlink_inode_operations_dotl;
320 else
321 inode->i_op = &v9fs_symlink_inode_operations;
322
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600323 break;
324 case S_IFDIR:
325 inc_nlink(inode);
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000326 if (v9fs_proto_dotl(v9ses))
327 inode->i_op = &v9fs_dir_inode_operations_dotl;
328 else if (v9fs_proto_dotu(v9ses))
329 inode->i_op = &v9fs_dir_inode_operations_dotu;
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600330 else
331 inode->i_op = &v9fs_dir_inode_operations;
Sripathi Kodi9b6533c2010-03-25 12:41:54 +0000332
333 if (v9fs_proto_dotl(v9ses))
334 inode->i_fop = &v9fs_dir_operations_dotl;
335 else
336 inode->i_fop = &v9fs_dir_operations;
337
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600338 break;
339 default:
340 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
341 mode, mode & S_IFMT);
342 err = -EINVAL;
343 goto error;
344 }
345
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700346 return inode;
Abhishek Kulkarni2bb54112009-07-19 13:41:56 -0600347
348error:
349 iput(inode);
350 return ERR_PTR(err);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700351}
352
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500353/*
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800354static struct v9fs_fid*
355v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
356{
357 int err;
Mika Kukkonen736c4b82006-12-06 20:36:29 -0800358 int nfid;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800359 struct v9fs_fid *ret;
360 struct v9fs_fcall *fcall;
361
362 nfid = v9fs_get_idpool(&v9ses->fidpool);
363 if (nfid < 0) {
364 eprintk(KERN_WARNING, "no free fids available\n");
Latchesar Ionkov731805b2006-03-07 21:55:42 -0800365 return ERR_PTR(-ENOSPC);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800366 }
367
368 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
369 &fcall);
370
371 if (err < 0) {
Latchesar Ionkov41e5a6a2006-05-15 09:44:21 -0700372 if (fcall && fcall->id == RWALK)
373 goto clunk_fid;
374
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800375 PRINT_FCALL_ERROR("walk error", fcall);
376 v9fs_put_idpool(nfid, &v9ses->fidpool);
377 goto error;
378 }
379
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700380 kfree(fcall);
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800381 fcall = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800382 ret = v9fs_fid_create(v9ses, nfid);
383 if (!ret) {
384 err = -ENOMEM;
385 goto clunk_fid;
386 }
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700387
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800388 err = v9fs_fid_insert(ret, dentry);
389 if (err < 0) {
390 v9fs_fid_destroy(ret);
391 goto clunk_fid;
Latchesar Ionkov0b8dd172005-09-27 21:45:24 -0700392 }
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800393
394 return ret;
395
396clunk_fid:
397 v9fs_t_clunk(v9ses, nfid);
398
399error:
400 kfree(fcall);
401 return ERR_PTR(err);
402}
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500403*/
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800404
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500405
406/**
407 * v9fs_clear_inode - release an inode
408 * @inode: inode to release
409 *
410 */
Al Virob57922d2010-06-07 14:34:48 -0400411void v9fs_evict_inode(struct inode *inode)
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500412{
Al Virob57922d2010-06-07 14:34:48 -0400413 truncate_inode_pages(inode->i_mapping, 0);
414 end_writeback(inode);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500415 filemap_fdatawrite(inode->i_mapping);
416
417#ifdef CONFIG_9P_FSCACHE
418 v9fs_cache_inode_put_cookie(inode);
419#endif
420}
421
Aneesh Kumar K.V53c06f42011-01-10 13:51:47 -0600422struct inode *
Sripathi Kodif0853122010-07-12 20:07:23 +0530423v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid,
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800424 struct super_block *sb)
425{
426 int err, umode;
Sripathi Kodif0853122010-07-12 20:07:23 +0530427 struct inode *ret = NULL;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500428 struct p9_wstat *st;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800429
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500430 st = p9_client_stat(fid);
Abhishek Kulkarni02bc3562009-07-19 13:41:54 -0600431 if (IS_ERR(st))
432 return ERR_CAST(st);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800433
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500434 umode = p9mode2unixmode(v9ses, st->mode);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800435 ret = v9fs_get_inode(sb, umode);
436 if (IS_ERR(ret)) {
437 err = PTR_ERR(ret);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800438 goto error;
439 }
440
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500441 v9fs_stat2inode(st, ret, sb);
442 ret->i_ino = v9fs_qid2ino(&st->qid);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500443
444#ifdef CONFIG_9P_FSCACHE
445 v9fs_vcookie_set_qid(ret, &st->qid);
446 v9fs_cache_inode_get_cookie(ret);
447#endif
Abhishek Kulkarni02bc3562009-07-19 13:41:54 -0600448 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500449 kfree(st);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800450 return ret;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800451error:
Abhishek Kulkarni02bc3562009-07-19 13:41:54 -0600452 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500453 kfree(st);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800454 return ERR_PTR(err);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700455}
456
457/**
458 * v9fs_remove - helper function to remove files and directories
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -0700459 * @dir: directory inode that is being deleted
460 * @file: dentry that is being deleted
461 * @rmdir: removing a directory
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700462 *
463 */
464
465static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
466{
Aneesh Kumar K.Vd994f402010-03-29 18:14:50 -0500467 int retval;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500468 struct inode *file_inode;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500469 struct p9_fid *v9fid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700470
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500471 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700472 rmdir);
473
474 file_inode = file->d_inode;
Latchesar Ionkovc959df92007-04-23 14:41:11 -0700475 v9fid = v9fs_fid_clone(file);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500476 if (IS_ERR(v9fid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800477 return PTR_ERR(v9fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700478
Aneesh Kumar K.Vd994f402010-03-29 18:14:50 -0500479 retval = p9_client_remove(v9fid);
480 if (!retval)
481 drop_nlink(file_inode);
482 return retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700483}
484
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500485/**
486 * v9fs_create - Create a file
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600487 * @v9ses: session information
488 * @dir: directory that dentry is being created in
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500489 * @dentry: dentry that is being created
Abhishek Kulkarni0e155972009-07-19 13:41:55 -0600490 * @extension: 9p2000.u extension string to support devices, etc.
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500491 * @perm: create permissions
492 * @mode: open mode
493 *
494 */
495static struct p9_fid *
496v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
497 struct dentry *dentry, char *extension, u32 perm, u8 mode)
498{
499 int err;
500 char *name;
501 struct p9_fid *dfid, *ofid, *fid;
502 struct inode *inode;
503
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500504 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
505
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500506 err = 0;
507 ofid = NULL;
508 fid = NULL;
509 name = (char *) dentry->d_name.name;
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000510 dfid = v9fs_fid_lookup(dentry->d_parent);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500511 if (IS_ERR(dfid)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500512 err = PTR_ERR(dfid);
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000513 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
514 return ERR_PTR(err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500515 }
516
517 /* clone a fid to use for creation */
518 ofid = p9_client_walk(dfid, 0, NULL, 1);
519 if (IS_ERR(ofid)) {
520 err = PTR_ERR(ofid);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500521 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000522 return ERR_PTR(err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500523 }
524
525 err = p9_client_fcreate(ofid, name, perm, mode, extension);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500526 if (err < 0) {
527 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500528 goto error;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500529 }
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500530
531 /* now walk from the parent so we can get unopened fid */
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000532 fid = p9_client_walk(dfid, 1, &name, 1);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500533 if (IS_ERR(fid)) {
534 err = PTR_ERR(fid);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500535 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500536 fid = NULL;
537 goto error;
Venkateswararao Jujjuri6d27e642010-05-10 18:08:28 +0000538 }
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500539
540 /* instantiate inode and assign the unopened fid to the dentry */
541 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
542 if (IS_ERR(inode)) {
543 err = PTR_ERR(inode);
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500544 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500545 goto error;
546 }
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500547 d_instantiate(dentry, inode);
Abhishek Kulkarni50fb6d22009-07-19 13:41:57 -0600548 err = v9fs_fid_add(dentry, fid);
549 if (err < 0)
550 goto error;
551
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500552 return ofid;
553
554error:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500555 if (ofid)
556 p9_client_clunk(ofid);
557
558 if (fid)
559 p9_client_clunk(fid);
560
561 return ERR_PTR(err);
562}
563
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700564/**
565 * v9fs_vfs_create - VFS hook to create files
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600566 * @dir: directory inode that is being created
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700567 * @dentry: dentry that is being deleted
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800568 * @mode: create permissions
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700569 * @nd: path information
570 *
571 */
572
573static int
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800574v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700575 struct nameidata *nd)
576{
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800577 int err;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500578 u32 perm;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800579 int flags;
580 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500581 struct p9_fid *fid;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800582 struct file *filp;
583
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500584 err = 0;
585 fid = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800586 v9ses = v9fs_inode2v9ses(dir);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800587 perm = unixmode2p9mode(v9ses, mode);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800588 if (nd && nd->flags & LOOKUP_OPEN)
589 flags = nd->intent.open.flags - 1;
590 else
591 flags = O_RDWR;
592
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500593 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000594 v9fs_uflags2omode(flags,
595 v9fs_proto_dotu(v9ses)));
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500596 if (IS_ERR(fid)) {
597 err = PTR_ERR(fid);
598 fid = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800599 goto error;
600 }
601
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500602 /* if we are opening a file, assign the open fid to the file */
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800603 if (nd && nd->flags & LOOKUP_OPEN) {
Aneesh Kumar K.V877cb3d2010-09-22 12:42:30 +0530604 filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800605 if (IS_ERR(filp)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500606 err = PTR_ERR(filp);
607 goto error;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800608 }
609
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500610 filp->private_data = fid;
611 } else
612 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800613
614 return 0;
615
616error:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500617 if (fid)
618 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800619
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800620 return err;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700621}
622
623/**
624 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600625 * @dir: inode that is being unlinked
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700626 * @dentry: dentry that is being unlinked
627 * @mode: mode for new directory
628 *
629 */
630
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800631static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700632{
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800633 int err;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500634 u32 perm;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800635 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500636 struct p9_fid *fid;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800637
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500638 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
639 err = 0;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800640 v9ses = v9fs_inode2v9ses(dir);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800641 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500642 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
643 if (IS_ERR(fid)) {
644 err = PTR_ERR(fid);
645 fid = NULL;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800646 }
647
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500648 if (fid)
649 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800650
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800651 return err;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700652}
653
654/**
655 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
656 * @dir: inode that is being walked from
657 * @dentry: dentry that is being walked to?
658 * @nameidata: path data
659 *
660 */
661
Aneesh Kumar K.V53c06f42011-01-10 13:51:47 -0600662struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700663 struct nameidata *nameidata)
664{
665 struct super_block *sb;
666 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500667 struct p9_fid *dfid, *fid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700668 struct inode *inode;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500669 char *name;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700670 int result = 0;
671
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500672 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
Latchesar Ionkov731805b2006-03-07 21:55:42 -0800673 dir, dentry->d_name.name, dentry, nameidata);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700674
Sripathi Kodi11e9b492010-03-29 18:13:59 -0500675 if (dentry->d_name.len > NAME_MAX)
676 return ERR_PTR(-ENAMETOOLONG);
677
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700678 sb = dir->i_sb;
679 v9ses = v9fs_inode2v9ses(dir);
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +0530680 /* We can walk d_parent because we hold the dir->i_mutex */
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500681 dfid = v9fs_fid_lookup(dentry->d_parent);
682 if (IS_ERR(dfid))
David Howellse231c2e2008-02-07 00:15:26 -0800683 return ERR_CAST(dfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700684
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500685 name = (char *) dentry->d_name.name;
686 fid = p9_client_walk(dfid, 1, &name, 1);
687 if (IS_ERR(fid)) {
688 result = PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700689 if (result == -ENOENT) {
Aneesh Kumar K.V85e0df22010-05-14 13:04:39 +0000690 inode = NULL;
691 goto inst_out;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700692 }
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700693
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500694 return ERR_PTR(result);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700695 }
696
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500697 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
698 if (IS_ERR(inode)) {
699 result = PTR_ERR(inode);
700 inode = NULL;
701 goto error;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700702 }
703
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500704 result = v9fs_fid_add(dentry, fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800705 if (result < 0)
Aneesh Kumar K.V9856af82010-09-22 12:24:23 +0530706 goto error_iput;
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -0800707
Aneesh Kumar K.V85e0df22010-05-14 13:04:39 +0000708inst_out:
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700709 d_add(dentry, inode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700710 return NULL;
711
Aneesh Kumar K.V9856af82010-09-22 12:24:23 +0530712error_iput:
713 iput(inode);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500714error:
Julien Brunel62aa5282008-09-24 16:22:22 -0500715 p9_client_clunk(fid);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800716
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700717 return ERR_PTR(result);
718}
719
720/**
721 * v9fs_vfs_unlink - VFS unlink hook to delete an inode
722 * @i: inode that is being unlinked
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -0700723 * @d: dentry that is being unlinked
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700724 *
725 */
726
Aneesh Kumar K.V53c06f42011-01-10 13:51:47 -0600727int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700728{
729 return v9fs_remove(i, d, 0);
730}
731
732/**
733 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
734 * @i: inode that is being unlinked
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -0700735 * @d: dentry that is being unlinked
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700736 *
737 */
738
Aneesh Kumar K.V53c06f42011-01-10 13:51:47 -0600739int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700740{
741 return v9fs_remove(i, d, 1);
742}
743
744/**
745 * v9fs_vfs_rename - VFS hook to rename an inode
746 * @old_dir: old dir inode
747 * @old_dentry: old dentry
748 * @new_dir: new dir inode
749 * @new_dentry: new dentry
750 *
751 */
752
Aneesh Kumar K.V53c06f42011-01-10 13:51:47 -0600753int
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700754v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
755 struct inode *new_dir, struct dentry *new_dentry)
756{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500757 struct inode *old_inode;
758 struct v9fs_session_info *v9ses;
759 struct p9_fid *oldfid;
760 struct p9_fid *olddirfid;
761 struct p9_fid *newdirfid;
762 struct p9_wstat wstat;
763 int retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700764
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500765 P9_DPRINTK(P9_DEBUG_VFS, "\n");
766 retval = 0;
767 old_inode = old_dentry->d_inode;
768 v9ses = v9fs_inode2v9ses(old_inode);
769 oldfid = v9fs_fid_lookup(old_dentry);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500770 if (IS_ERR(oldfid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800771 return PTR_ERR(oldfid);
772
773 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500774 if (IS_ERR(olddirfid)) {
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800775 retval = PTR_ERR(olddirfid);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500776 goto done;
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800777 }
778
779 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500780 if (IS_ERR(newdirfid)) {
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800781 retval = PTR_ERR(newdirfid);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500782 goto clunk_olddir;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700783 }
784
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +0530785 down_write(&v9ses->rename_sem);
Sripathi Kodi4681dbd2010-03-25 12:47:26 +0000786 if (v9fs_proto_dotl(v9ses)) {
787 retval = p9_client_rename(oldfid, newdirfid,
788 (char *) new_dentry->d_name.name);
789 if (retval != -ENOSYS)
790 goto clunk_newdir;
791 }
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +0530792 if (old_dentry->d_parent != new_dentry->d_parent) {
793 /*
794 * 9P .u can only handle file rename in the same directory
795 */
Sripathi Kodi4681dbd2010-03-25 12:47:26 +0000796
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500797 P9_DPRINTK(P9_DEBUG_ERROR,
798 "old dir and new dir are different\n");
Eric Van Hensbergen621997c2007-01-26 00:57:04 -0800799 retval = -EXDEV;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500800 goto clunk_newdir;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700801 }
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800802 v9fs_blank_wstat(&wstat);
Latchesar Ionkovba176742007-10-17 14:31:07 -0500803 wstat.muid = v9ses->uname;
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800804 wstat.name = (char *) new_dentry->d_name.name;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500805 retval = p9_client_wstat(oldfid, &wstat);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700806
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500807clunk_newdir:
Aneesh Kumar K.Va534c8d2010-06-30 19:18:50 +0530808 if (!retval)
809 /* successful rename */
810 d_move(old_dentry, new_dentry);
811 up_write(&v9ses->rename_sem);
Latchesar Ionkov22150c42007-10-23 13:48:33 -0500812 p9_client_clunk(newdirfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700813
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500814clunk_olddir:
Latchesar Ionkov22150c42007-10-23 13:48:33 -0500815 p9_client_clunk(olddirfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700816
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500817done:
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700818 return retval;
819}
820
821/**
Adrian Bunk943ffb52006-01-10 00:10:13 +0100822 * v9fs_vfs_getattr - retrieve file metadata
Eric Van Hensbergenee443992008-03-05 07:08:09 -0600823 * @mnt: mount information
824 * @dentry: file to get attributes on
825 * @stat: metadata structure to populate
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700826 *
827 */
828
829static int
830v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
831 struct kstat *stat)
832{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500833 int err;
834 struct v9fs_session_info *v9ses;
835 struct p9_fid *fid;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500836 struct p9_wstat *st;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700837
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500838 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
839 err = -EPERM;
840 v9ses = v9fs_inode2v9ses(dentry->d_inode);
Abhishek Kulkarni60e78d22009-09-23 13:00:27 -0500841 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
Eric Van Hensbergen9523a842007-07-13 13:01:27 -0500842 return simple_getattr(mnt, dentry, stat);
843
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500844 fid = v9fs_fid_lookup(dentry);
845 if (IS_ERR(fid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800846 return PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700847
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500848 st = p9_client_stat(fid);
849 if (IS_ERR(st))
850 return PTR_ERR(st);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700851
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500852 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700853 generic_fillattr(dentry->d_inode, stat);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700854
Latchesar Ionkov62b2be52010-08-24 18:13:59 +0000855 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500856 kfree(st);
857 return 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700858}
859
860/**
861 * v9fs_vfs_setattr - set file metadata
862 * @dentry: file whose metadata to set
863 * @iattr: metadata assignment structure
864 *
865 */
866
867static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
868{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500869 int retval;
870 struct v9fs_session_info *v9ses;
871 struct p9_fid *fid;
872 struct p9_wstat wstat;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700873
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500874 P9_DPRINTK(P9_DEBUG_VFS, "\n");
875 retval = -EPERM;
876 v9ses = v9fs_inode2v9ses(dentry->d_inode);
877 fid = v9fs_fid_lookup(dentry);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -0800878 if(IS_ERR(fid))
879 return PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700880
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800881 v9fs_blank_wstat(&wstat);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700882 if (iattr->ia_valid & ATTR_MODE)
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800883 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700884
885 if (iattr->ia_valid & ATTR_MTIME)
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800886 wstat.mtime = iattr->ia_mtime.tv_sec;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700887
888 if (iattr->ia_valid & ATTR_ATIME)
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800889 wstat.atime = iattr->ia_atime.tv_sec;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700890
891 if (iattr->ia_valid & ATTR_SIZE)
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800892 wstat.length = iattr->ia_size;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700893
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000894 if (v9fs_proto_dotu(v9ses)) {
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800895 if (iattr->ia_valid & ATTR_UID)
896 wstat.n_uid = iattr->ia_uid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700897
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800898 if (iattr->ia_valid & ATTR_GID)
899 wstat.n_gid = iattr->ia_gid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700900 }
901
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500902 retval = p9_client_wstat(fid, &wstat);
Christoph Hellwig10257742010-06-04 11:30:02 +0200903 if (retval < 0)
904 return retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700905
Christoph Hellwig10257742010-06-04 11:30:02 +0200906 if ((iattr->ia_valid & ATTR_SIZE) &&
907 iattr->ia_size != i_size_read(dentry->d_inode)) {
908 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
909 if (retval)
910 return retval;
911 }
912
913 setattr_copy(dentry->d_inode, iattr);
914 mark_inode_dirty(dentry->d_inode);
915 return 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700916}
917
918/**
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800919 * v9fs_stat2inode - populate an inode structure with mistat info
920 * @stat: Plan 9 metadata (mistat) structure
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700921 * @inode: inode to populate
922 * @sb: superblock of filesystem
923 *
924 */
925
926void
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500927v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800928 struct super_block *sb)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700929{
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800930 char ext[32];
Aneesh Kumar K.V57171442010-03-05 14:43:43 -0600931 char tag_name[14];
932 unsigned int i_nlink;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700933 struct v9fs_session_info *v9ses = sb->s_fs_info;
934
935 inode->i_nlink = 1;
936
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800937 inode->i_atime.tv_sec = stat->atime;
938 inode->i_mtime.tv_sec = stat->mtime;
939 inode->i_ctime.tv_sec = stat->mtime;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700940
Latchesar Ionkovbd32b822007-10-17 14:31:07 -0500941 inode->i_uid = v9ses->dfltuid;
942 inode->i_gid = v9ses->dfltgid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700943
Sripathi Kodidd6102f2010-03-05 18:48:00 +0000944 if (v9fs_proto_dotu(v9ses)) {
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800945 inode->i_uid = stat->n_uid;
946 inode->i_gid = stat->n_gid;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700947 }
Aneesh Kumar K.V57171442010-03-05 14:43:43 -0600948 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
949 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
950 /*
951 * Hadlink support got added later to
952 * to the .u extension. So there can be
953 * server out there that doesn't support
954 * this even with .u extension. So check
955 * for non NULL stat->extension
956 */
957 strncpy(ext, stat->extension, sizeof(ext));
958 /* HARDLINKCOUNT %u */
959 sscanf(ext, "%13s %u", tag_name, &i_nlink);
960 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
961 inode->i_nlink = i_nlink;
962 }
963 }
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800964 inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700965 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
966 char type = 0;
967 int major = -1;
968 int minor = -1;
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800969
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500970 strncpy(ext, stat->extension, sizeof(ext));
Latchesar Ionkov531b1092006-01-08 01:05:00 -0800971 sscanf(ext, "%c %u %u", &type, &major, &minor);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700972 switch (type) {
973 case 'c':
974 inode->i_mode &= ~S_IFBLK;
975 inode->i_mode |= S_IFCHR;
976 break;
977 case 'b':
978 break;
979 default:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500980 P9_DPRINTK(P9_DEBUG_ERROR,
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -0500981 "Unknown special type %c %s\n", type,
982 stat->extension);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700983 };
984 inode->i_rdev = MKDEV(major, minor);
Magnus Deininger57c7b4e2008-10-17 12:44:46 -0500985 init_special_inode(inode, inode->i_mode, inode->i_rdev);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700986 } else
987 inode->i_rdev = 0;
988
Abhishek Kulkarni7549ae32009-09-22 11:34:05 -0500989 i_size_write(inode, stat->length);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700990
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -0500991 /* not real number of blocks, but 512 byte ones ... */
Abhishek Kulkarni7549ae32009-09-22 11:34:05 -0500992 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -0700993}
994
995/**
996 * v9fs_qid2ino - convert qid into inode number
997 * @qid: qid to hash
998 *
999 * BUG: potential for inode number collisions?
1000 */
1001
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001002ino_t v9fs_qid2ino(struct p9_qid *qid)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001003{
1004 u64 path = qid->path + 2;
1005 ino_t i = 0;
1006
1007 if (sizeof(ino_t) == sizeof(path))
1008 memcpy(&i, &path, sizeof(ino_t));
1009 else
1010 i = (ino_t) (path ^ (path >> 32));
1011
1012 return i;
1013}
1014
1015/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001016 * v9fs_readlink - read a symlink's location (internal version)
1017 * @dentry: dentry for symlink
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001018 * @buffer: buffer to load symlink location into
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001019 * @buflen: length of buffer
1020 *
1021 */
1022
1023static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1024{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001025 int retval;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001026
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001027 struct v9fs_session_info *v9ses;
1028 struct p9_fid *fid;
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001029 struct p9_wstat *st;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001030
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001031 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1032 retval = -EPERM;
1033 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1034 fid = v9fs_fid_lookup(dentry);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001035 if (IS_ERR(fid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001036 return PTR_ERR(fid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001037
M. Mohan Kumar329176c2010-09-28 19:59:25 +05301038 if (!v9fs_proto_dotu(v9ses))
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001039 return -EBADF;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001040
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001041 st = p9_client_stat(fid);
1042 if (IS_ERR(st))
1043 return PTR_ERR(st);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001044
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001045 if (!(st->mode & P9_DMSYMLINK)) {
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001046 retval = -EINVAL;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001047 goto done;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001048 }
1049
1050 /* copy extension buffer into buffer */
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001051 strncpy(buffer, st->extension, buflen);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001052
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001053 P9_DPRINTK(P9_DEBUG_VFS,
Eric Van Hensbergen51a87c52008-10-16 08:30:07 -05001054 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001055
Martin Stava2511cd02009-11-02 08:39:34 -06001056 retval = strnlen(buffer, buflen);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001057done:
Latchesar Ionkov62b2be52010-08-24 18:13:59 +00001058 p9stat_free(st);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001059 kfree(st);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001060 return retval;
1061}
1062
1063/**
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001064 * v9fs_vfs_follow_link - follow a symlink path
1065 * @dentry: dentry for symlink
1066 * @nd: nameidata
1067 *
1068 */
1069
1070static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1071{
1072 int len = 0;
1073 char *link = __getname();
1074
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001075 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001076
1077 if (!link)
1078 link = ERR_PTR(-ENOMEM);
1079 else {
Latchesar Ionkov16cce6d2006-03-25 03:07:26 -08001080 len = v9fs_readlink(dentry, link, PATH_MAX);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001081
1082 if (len < 0) {
Davi Arnautce44eeb2005-11-07 00:59:36 -08001083 __putname(link);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001084 link = ERR_PTR(len);
1085 } else
Martin Stava2511cd02009-11-02 08:39:34 -06001086 link[min(len, PATH_MAX-1)] = 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001087 }
1088 nd_set_link(nd, link);
1089
1090 return NULL;
1091}
1092
1093/**
1094 * v9fs_vfs_put_link - release a symlink path
1095 * @dentry: dentry for symlink
1096 * @nd: nameidata
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001097 * @p: unused
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001098 *
1099 */
1100
Aneesh Kumar K.V53c06f42011-01-10 13:51:47 -06001101void
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001102v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001103{
1104 char *s = nd_get_link(nd);
1105
Duane Griffin6ff23202008-12-19 16:45:21 -06001106 P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
1107 IS_ERR(s) ? "<error>" : s);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001108 if (!IS_ERR(s))
Davi Arnautce44eeb2005-11-07 00:59:36 -08001109 __putname(s);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001110}
1111
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001112/**
1113 * v9fs_vfs_mkspecial - create a special file
1114 * @dir: inode to create special file in
1115 * @dentry: dentry to create
1116 * @mode: mode to create special file
1117 * @extension: 9p2000.u format extension string representing special file
1118 *
1119 */
1120
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001121static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1122 int mode, const char *extension)
1123{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001124 u32 perm;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001125 struct v9fs_session_info *v9ses;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001126 struct p9_fid *fid;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001127
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001128 v9ses = v9fs_inode2v9ses(dir);
Sripathi Kodidd6102f2010-03-05 18:48:00 +00001129 if (!v9fs_proto_dotu(v9ses)) {
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001130 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001131 return -EPERM;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001132 }
1133
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001134 perm = unixmode2p9mode(v9ses, mode);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001135 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1136 P9_OREAD);
1137 if (IS_ERR(fid))
1138 return PTR_ERR(fid);
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001139
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001140 p9_client_clunk(fid);
Latchesar Ionkov6a3124a2006-03-02 02:54:30 -08001141 return 0;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001142}
1143
1144/**
1145 * v9fs_vfs_symlink - helper function to create symlinks
1146 * @dir: directory inode containing symlink
1147 * @dentry: dentry for symlink
1148 * @symname: symlink data
1149 *
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001150 * See Also: 9P2000.u RFC for more information
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001151 *
1152 */
1153
1154static int
1155v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1156{
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001157 P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
1158 dentry->d_name.name, symname);
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001159
1160 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
1161}
1162
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001163/**
1164 * v9fs_vfs_link - create a hardlink
1165 * @old_dentry: dentry for file to link to
1166 * @dir: inode destination for new link
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001167 * @dentry: dentry for link
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001168 *
1169 */
1170
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001171static int
1172v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1173 struct dentry *dentry)
1174{
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001175 int retval;
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001176 struct p9_fid *oldfid;
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001177 char *name;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001178
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001179 P9_DPRINTK(P9_DEBUG_VFS,
1180 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001181 old_dentry->d_name.name);
1182
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001183 oldfid = v9fs_fid_clone(old_dentry);
Latchesar Ionkovba176742007-10-17 14:31:07 -05001184 if (IS_ERR(oldfid))
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001185 return PTR_ERR(oldfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001186
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001187 name = __getname();
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001188 if (unlikely(!name)) {
1189 retval = -ENOMEM;
1190 goto clunk_fid;
1191 }
Florin Malita0710d362006-06-25 05:48:31 -07001192
Latchesar Ionkov16cce6d2006-03-25 03:07:26 -08001193 sprintf(name, "%d\n", oldfid->fid);
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001194 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001195 __putname(name);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001196
Eric Van Hensbergenda977b22007-01-26 00:57:06 -08001197clunk_fid:
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001198 p9_client_clunk(oldfid);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001199 return retval;
1200}
1201
1202/**
1203 * v9fs_vfs_mknod - create a special file
1204 * @dir: inode destination for new link
1205 * @dentry: dentry for file
1206 * @mode: mode for creation
Eric Van Hensbergenee443992008-03-05 07:08:09 -06001207 * @rdev: device associated with special file
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001208 *
1209 */
1210
1211static int
1212v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1213{
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001214 int retval;
1215 char *name;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001216
Latchesar Ionkovbd238fb2007-07-10 17:57:28 -05001217 P9_DPRINTK(P9_DEBUG_VFS,
1218 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001219 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1220
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001221 if (!new_valid_dev(rdev))
1222 return -EINVAL;
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001223
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001224 name = __getname();
Eugene Teoc0291a02006-03-25 03:07:27 -08001225 if (!name)
1226 return -ENOMEM;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001227 /* build extension */
1228 if (S_ISBLK(mode))
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001229 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001230 else if (S_ISCHR(mode))
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001231 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
Eric Van Hensbergen73c592b2005-09-09 13:04:26 -07001232 else if (S_ISFIFO(mode))
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001233 *name = 0;
Venkateswararao Jujjuri75cc5c92010-05-22 12:20:30 -05001234 else if (S_ISSOCK(mode))
1235 *name = 0;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001236 else {
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001237 __putname(name);
1238 return -EINVAL;
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001239 }
1240
Latchesar Ionkov531b1092006-01-08 01:05:00 -08001241 retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
1242 __putname(name);
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001243
1244 return retval;
1245}
1246
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00001247static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1248 .create = v9fs_vfs_create,
1249 .lookup = v9fs_vfs_lookup,
1250 .symlink = v9fs_vfs_symlink,
Venkateswararao Jujjuri (JV)50cc42f2010-06-09 15:59:31 -07001251 .link = v9fs_vfs_link,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00001252 .unlink = v9fs_vfs_unlink,
1253 .mkdir = v9fs_vfs_mkdir,
1254 .rmdir = v9fs_vfs_rmdir,
Aneesh Kumar K.V1d76e312010-08-30 17:43:07 +00001255 .mknod = v9fs_vfs_mknod,
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00001256 .rename = v9fs_vfs_rename,
1257 .getattr = v9fs_vfs_getattr,
1258 .setattr = v9fs_vfs_setattr,
1259};
1260
Arjan van de Ven754661f2007-02-12 00:55:38 -08001261static const struct inode_operations v9fs_dir_inode_operations = {
Eric Van Hensbergenb5016112005-09-09 13:04:27 -07001262 .create = v9fs_vfs_create,
1263 .lookup = v9fs_vfs_lookup,
1264 .unlink = v9fs_vfs_unlink,
1265 .mkdir = v9fs_vfs_mkdir,
1266 .rmdir = v9fs_vfs_rmdir,
1267 .mknod = v9fs_vfs_mknod,
1268 .rename = v9fs_vfs_rename,
1269 .getattr = v9fs_vfs_getattr,
1270 .setattr = v9fs_vfs_setattr,
1271};
1272
Arjan van de Ven754661f2007-02-12 00:55:38 -08001273static const struct inode_operations v9fs_file_inode_operations = {
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001274 .getattr = v9fs_vfs_getattr,
1275 .setattr = v9fs_vfs_setattr,
1276};
1277
Arjan van de Ven754661f2007-02-12 00:55:38 -08001278static const struct inode_operations v9fs_symlink_inode_operations = {
Al Viro204f2f02009-12-23 00:35:54 -05001279 .readlink = generic_readlink,
Eric Van Hensbergen2bad8472005-09-09 13:04:19 -07001280 .follow_link = v9fs_vfs_follow_link,
1281 .put_link = v9fs_vfs_put_link,
1282 .getattr = v9fs_vfs_getattr,
1283 .setattr = v9fs_vfs_setattr,
1284};
Sripathi Kodi9b6533c2010-03-25 12:41:54 +00001285