blob: 6e478f4765ef35416139049e72da1936d161695c [file] [log] [blame]
Anthony Liguori9f107512010-04-29 17:44:44 +05301/*
Wei Liuf00d4f52015-11-18 18:05:29 +00002 * 9p Posix callback
Anthony Liguori9f107512010-04-29 17:44:44 +05303 *
4 * Copyright IBM, Corp. 2010
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 */
Stefan Weil873c3212011-06-01 12:35:14 +053013
Peter Maydellfbc04122016-01-26 18:17:10 +000014#include "qemu/osdep.h"
Wei Liuebe74f82016-01-07 18:18:02 +000015#include "9p.h"
Greg Kurz996a0d72017-02-26 23:42:18 +010016#include "9p-local.h"
Wei Liu267ae092015-11-18 18:31:52 +000017#include "9p-xattr.h"
Greg Kurz0e35a372017-02-26 23:42:10 +010018#include "9p-util.h"
Stefan Weil69b15212014-05-02 22:22:32 +020019#include "fsdev/qemu-fsdev.h" /* local_ops */
Anthony Liguoric494dd62010-04-29 17:44:59 +053020#include <arpa/inet.h>
Anthony Liguori131dcb22010-04-29 17:44:47 +053021#include <pwd.h>
22#include <grp.h>
Anthony Liguoric494dd62010-04-29 17:44:59 +053023#include <sys/socket.h>
24#include <sys/un.h>
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010025#include "qemu/xattr.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020026#include "qemu/cutils.h"
Greg Kurz63325b12016-01-22 15:12:17 +010027#include "qemu/error-report.h"
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +053028#include <libgen.h>
Harsh Prateek Borae06a7652011-10-12 19:11:25 +053029#include <linux/fs.h>
30#ifdef CONFIG_LINUX_MAGIC_H
31#include <linux/magic.h>
32#endif
33#include <sys/ioctl.h>
34
35#ifndef XFS_SUPER_MAGIC
36#define XFS_SUPER_MAGIC 0x58465342
37#endif
38#ifndef EXT2_SUPER_MAGIC
39#define EXT2_SUPER_MAGIC 0xEF53
40#endif
41#ifndef REISERFS_SUPER_MAGIC
42#define REISERFS_SUPER_MAGIC 0x52654973
43#endif
44#ifndef BTRFS_SUPER_MAGIC
45#define BTRFS_SUPER_MAGIC 0x9123683E
46#endif
Anthony Liguori131dcb22010-04-29 17:44:47 +053047
Greg Kurz0e35a372017-02-26 23:42:10 +010048typedef struct {
49 int mountfd;
50} LocalData;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +053051
Greg Kurz996a0d72017-02-26 23:42:18 +010052int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
53 mode_t mode)
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +053054{
Greg Kurz996a0d72017-02-26 23:42:18 +010055 LocalData *data = fs_ctx->private;
Greg Kurz3dbcf272017-05-25 10:30:14 +020056 int fd = data->mountfd;
Greg Kurz996a0d72017-02-26 23:42:18 +010057
Greg Kurz3dbcf272017-05-25 10:30:14 +020058 while (*path && fd != -1) {
59 const char *c;
60 int next_fd;
61 char *head;
62
63 /* Only relative paths without consecutive slashes */
64 assert(*path != '/');
65
66 head = g_strdup(path);
67 c = strchrnul(path, '/');
68 if (*c) {
69 /* Intermediate path element */
70 head[c - path] = 0;
71 path = c + 1;
72 next_fd = openat_dir(fd, head);
73 } else {
74 /* Rightmost path element */
75 next_fd = openat_file(fd, head, flags, mode);
76 path = c;
77 }
78 g_free(head);
79 if (fd != data->mountfd) {
80 close_preserve_errno(fd);
81 }
82 fd = next_fd;
Michael Tokarev1b6f85e2015-03-12 09:52:30 +030083 }
Greg Kurz996a0d72017-02-26 23:42:18 +010084
Greg Kurz3dbcf272017-05-25 10:30:14 +020085 assert(fd != data->mountfd);
86 return fd;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +053087}
88
Greg Kurz996a0d72017-02-26 23:42:18 +010089int local_opendir_nofollow(FsContext *fs_ctx, const char *path)
90{
91 return local_open_nofollow(fs_ctx, path, O_DIRECTORY | O_RDONLY, 0);
92}
93
Greg Kurz99f2cf42017-02-26 23:43:55 +010094static void renameat_preserve_errno(int odirfd, const char *opath, int ndirfd,
95 const char *npath)
96{
97 int serrno = errno;
98 renameat(odirfd, opath, ndirfd, npath);
99 errno = serrno;
100}
101
Greg Kurzad0b46e2017-02-26 23:44:20 +0100102static void unlinkat_preserve_errno(int dirfd, const char *path, int flags)
103{
104 int serrno = errno;
105 unlinkat(dirfd, path, flags);
106 errno = serrno;
107}
108
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530109#define VIRTFS_META_DIR ".virtfs_metadata"
Greg Kurz81ffbf52017-05-25 10:30:14 +0200110#define VIRTFS_META_ROOT_FILE VIRTFS_META_DIR "_root"
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530111
Greg Kurzf9aef992017-02-26 23:43:48 +0100112static FILE *local_fopenat(int dirfd, const char *name, const char *mode)
Aneesh Kumar K.V0ceb0922013-05-20 19:43:15 +0530113{
114 int fd, o_mode = 0;
115 FILE *fp;
Greg Kurzf9aef992017-02-26 23:43:48 +0100116 int flags;
Aneesh Kumar K.V0ceb0922013-05-20 19:43:15 +0530117 /*
118 * only supports two modes
119 */
120 if (mode[0] == 'r') {
Greg Kurzf9aef992017-02-26 23:43:48 +0100121 flags = O_RDONLY;
Aneesh Kumar K.V0ceb0922013-05-20 19:43:15 +0530122 } else if (mode[0] == 'w') {
Greg Kurzf9aef992017-02-26 23:43:48 +0100123 flags = O_WRONLY | O_TRUNC | O_CREAT;
Aneesh Kumar K.V0ceb0922013-05-20 19:43:15 +0530124 o_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
125 } else {
126 return NULL;
127 }
Greg Kurzf9aef992017-02-26 23:43:48 +0100128 fd = openat_file(dirfd, name, flags, o_mode);
Aneesh Kumar K.V0ceb0922013-05-20 19:43:15 +0530129 if (fd == -1) {
130 return NULL;
131 }
132 fp = fdopen(fd, mode);
133 if (!fp) {
134 close(fd);
135 }
136 return fp;
137}
138
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530139#define ATTR_MAX 100
Greg Kurzf9aef992017-02-26 23:43:48 +0100140static void local_mapped_file_attr(int dirfd, const char *name,
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530141 struct stat *stbuf)
142{
143 FILE *fp;
144 char buf[ATTR_MAX];
Greg Kurzf9aef992017-02-26 23:43:48 +0100145 int map_dirfd;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530146
Greg Kurz81ffbf52017-05-25 10:30:14 +0200147 if (strcmp(name, ".")) {
148 map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR);
149 if (map_dirfd == -1) {
150 return;
151 }
Greg Kurzf9aef992017-02-26 23:43:48 +0100152
Greg Kurz81ffbf52017-05-25 10:30:14 +0200153 fp = local_fopenat(map_dirfd, name, "r");
154 close_preserve_errno(map_dirfd);
155 } else {
156 fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "r");
157 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530158 if (!fp) {
159 return;
160 }
161 memset(buf, 0, ATTR_MAX);
162 while (fgets(buf, ATTR_MAX, fp)) {
163 if (!strncmp(buf, "virtfs.uid", 10)) {
164 stbuf->st_uid = atoi(buf+11);
165 } else if (!strncmp(buf, "virtfs.gid", 10)) {
166 stbuf->st_gid = atoi(buf+11);
167 } else if (!strncmp(buf, "virtfs.mode", 11)) {
168 stbuf->st_mode = atoi(buf+12);
169 } else if (!strncmp(buf, "virtfs.rdev", 11)) {
170 stbuf->st_rdev = atoi(buf+12);
171 }
172 memset(buf, 0, ATTR_MAX);
173 }
174 fclose(fp);
175}
176
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530177static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
Anthony Liguori131dcb22010-04-29 17:44:47 +0530178{
Greg Kurzf9aef992017-02-26 23:43:48 +0100179 int err = -1;
180 char *dirpath = g_path_get_dirname(fs_path->data);
181 char *name = g_path_get_basename(fs_path->data);
182 int dirfd;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530183
Greg Kurzf9aef992017-02-26 23:43:48 +0100184 dirfd = local_opendir_nofollow(fs_ctx, dirpath);
185 if (dirfd == -1) {
186 goto out;
187 }
188
189 err = fstatat(dirfd, name, stbuf, AT_SYMLINK_NOFOLLOW);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700190 if (err) {
Chen Gang4fa4ce72014-03-02 01:36:19 +0800191 goto err_out;
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700192 }
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530193 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700194 /* Actual credentials are part of extended attrs */
195 uid_t tmp_uid;
196 gid_t tmp_gid;
197 mode_t tmp_mode;
198 dev_t tmp_dev;
Greg Kurzf9aef992017-02-26 23:43:48 +0100199
200 if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.uid", &tmp_uid,
201 sizeof(uid_t)) > 0) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530202 stbuf->st_uid = le32_to_cpu(tmp_uid);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700203 }
Greg Kurzf9aef992017-02-26 23:43:48 +0100204 if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.gid", &tmp_gid,
205 sizeof(gid_t)) > 0) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530206 stbuf->st_gid = le32_to_cpu(tmp_gid);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700207 }
Greg Kurzf9aef992017-02-26 23:43:48 +0100208 if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.mode", &tmp_mode,
209 sizeof(mode_t)) > 0) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530210 stbuf->st_mode = le32_to_cpu(tmp_mode);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700211 }
Greg Kurzf9aef992017-02-26 23:43:48 +0100212 if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.rdev", &tmp_dev,
213 sizeof(dev_t)) > 0) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530214 stbuf->st_rdev = le64_to_cpu(tmp_dev);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700215 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530216 } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Greg Kurzf9aef992017-02-26 23:43:48 +0100217 local_mapped_file_attr(dirfd, name, stbuf);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700218 }
Chen Gang4fa4ce72014-03-02 01:36:19 +0800219
220err_out:
Greg Kurzf9aef992017-02-26 23:43:48 +0100221 close_preserve_errno(dirfd);
222out:
223 g_free(name);
224 g_free(dirpath);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700225 return err;
Anthony Liguori131dcb22010-04-29 17:44:47 +0530226}
227
Greg Kurze3187a42017-02-26 23:44:28 +0100228static int local_set_mapped_file_attrat(int dirfd, const char *name,
229 FsCred *credp)
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530230{
231 FILE *fp;
Greg Kurze3187a42017-02-26 23:44:28 +0100232 int ret;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530233 char buf[ATTR_MAX];
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530234 int uid = -1, gid = -1, mode = -1, rdev = -1;
Greg Kurz81ffbf52017-05-25 10:30:14 +0200235 int map_dirfd = -1, map_fd;
236 bool is_root = !strcmp(name, ".");
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530237
Greg Kurz81ffbf52017-05-25 10:30:14 +0200238 if (is_root) {
239 fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "r");
240 if (!fp) {
241 if (errno == ENOENT) {
242 goto update_map_file;
243 } else {
244 return -1;
245 }
246 }
247 } else {
248 ret = mkdirat(dirfd, VIRTFS_META_DIR, 0700);
249 if (ret < 0 && errno != EEXIST) {
Greg Kurze3187a42017-02-26 23:44:28 +0100250 return -1;
251 }
Greg Kurz81ffbf52017-05-25 10:30:14 +0200252
253 map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR);
254 if (map_dirfd == -1) {
255 return -1;
256 }
257
258 fp = local_fopenat(map_dirfd, name, "r");
259 if (!fp) {
260 if (errno == ENOENT) {
261 goto update_map_file;
262 } else {
263 close_preserve_errno(map_dirfd);
264 return -1;
265 }
266 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530267 }
268 memset(buf, 0, ATTR_MAX);
269 while (fgets(buf, ATTR_MAX, fp)) {
270 if (!strncmp(buf, "virtfs.uid", 10)) {
Greg Kurze3187a42017-02-26 23:44:28 +0100271 uid = atoi(buf + 11);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530272 } else if (!strncmp(buf, "virtfs.gid", 10)) {
Greg Kurze3187a42017-02-26 23:44:28 +0100273 gid = atoi(buf + 11);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530274 } else if (!strncmp(buf, "virtfs.mode", 11)) {
Greg Kurze3187a42017-02-26 23:44:28 +0100275 mode = atoi(buf + 12);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530276 } else if (!strncmp(buf, "virtfs.rdev", 11)) {
Greg Kurze3187a42017-02-26 23:44:28 +0100277 rdev = atoi(buf + 12);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530278 }
279 memset(buf, 0, ATTR_MAX);
280 }
281 fclose(fp);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530282
283update_map_file:
Greg Kurz81ffbf52017-05-25 10:30:14 +0200284 if (is_root) {
285 fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "w");
286 } else {
287 fp = local_fopenat(map_dirfd, name, "w");
288 /* We can't go this far with map_dirfd not being a valid file descriptor
289 * but some versions of gcc aren't smart enough to see it.
290 */
291 if (map_dirfd != -1) {
292 close_preserve_errno(map_dirfd);
293 }
294 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530295 if (!fp) {
Greg Kurze3187a42017-02-26 23:44:28 +0100296 return -1;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530297 }
298
Greg Kurz81ffbf52017-05-25 10:30:14 +0200299 map_fd = fileno(fp);
300 assert(map_fd != -1);
301 ret = fchmod(map_fd, 0600);
302 assert(ret == 0);
303
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530304 if (credp->fc_uid != -1) {
305 uid = credp->fc_uid;
306 }
307 if (credp->fc_gid != -1) {
308 gid = credp->fc_gid;
309 }
310 if (credp->fc_mode != -1) {
311 mode = credp->fc_mode;
312 }
313 if (credp->fc_rdev != -1) {
314 rdev = credp->fc_rdev;
315 }
316
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530317 if (uid != -1) {
318 fprintf(fp, "virtfs.uid=%d\n", uid);
319 }
320 if (gid != -1) {
321 fprintf(fp, "virtfs.gid=%d\n", gid);
322 }
323 if (mode != -1) {
324 fprintf(fp, "virtfs.mode=%d\n", mode);
325 }
326 if (rdev != -1) {
327 fprintf(fp, "virtfs.rdev=%d\n", rdev);
328 }
329 fclose(fp);
330
Greg Kurze3187a42017-02-26 23:44:28 +0100331 return 0;
332}
333
334static int fchmodat_nofollow(int dirfd, const char *name, mode_t mode)
335{
336 int fd, ret;
337
338 /* FIXME: this should be handled with fchmodat(AT_SYMLINK_NOFOLLOW).
339 * Unfortunately, the linux kernel doesn't implement it yet. As an
340 * alternative, let's open the file and use fchmod() instead. This
341 * may fail depending on the permissions of the file, but it is the
342 * best we can do to avoid TOCTTOU. We first try to open read-only
343 * in case name points to a directory. If that fails, we try write-only
344 * in case name doesn't point to a directory.
345 */
346 fd = openat_file(dirfd, name, O_RDONLY, 0);
347 if (fd == -1) {
348 /* In case the file is writable-only and isn't a directory. */
349 if (errno == EACCES) {
350 fd = openat_file(dirfd, name, O_WRONLY, 0);
351 }
352 if (fd == -1 && errno == EISDIR) {
353 errno = EACCES;
354 }
355 }
356 if (fd == -1) {
357 return -1;
358 }
359 ret = fchmod(fd, mode);
360 close_preserve_errno(fd);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530361 return ret;
362}
363
Greg Kurze3187a42017-02-26 23:44:28 +0100364static int local_set_xattrat(int dirfd, const char *path, FsCred *credp)
Anthony Liguori131dcb22010-04-29 17:44:47 +0530365{
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700366 int err;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530367
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700368 if (credp->fc_uid != -1) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530369 uint32_t tmp_uid = cpu_to_le32(credp->fc_uid);
Greg Kurze3187a42017-02-26 23:44:28 +0100370 err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.uid", &tmp_uid,
371 sizeof(uid_t), 0);
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700372 if (err) {
373 return err;
374 }
Anthony Liguori131dcb22010-04-29 17:44:47 +0530375 }
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700376 if (credp->fc_gid != -1) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530377 uint32_t tmp_gid = cpu_to_le32(credp->fc_gid);
Greg Kurze3187a42017-02-26 23:44:28 +0100378 err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.gid", &tmp_gid,
379 sizeof(gid_t), 0);
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700380 if (err) {
381 return err;
382 }
Anthony Liguori131dcb22010-04-29 17:44:47 +0530383 }
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700384 if (credp->fc_mode != -1) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530385 uint32_t tmp_mode = cpu_to_le32(credp->fc_mode);
Greg Kurze3187a42017-02-26 23:44:28 +0100386 err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.mode", &tmp_mode,
387 sizeof(mode_t), 0);
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700388 if (err) {
389 return err;
390 }
Anthony Liguori131dcb22010-04-29 17:44:47 +0530391 }
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700392 if (credp->fc_rdev != -1) {
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530393 uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev);
Greg Kurze3187a42017-02-26 23:44:28 +0100394 err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.rdev", &tmp_rdev,
395 sizeof(dev_t), 0);
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700396 if (err) {
397 return err;
398 }
Anthony Liguori131dcb22010-04-29 17:44:47 +0530399 }
Anthony Liguori131dcb22010-04-29 17:44:47 +0530400 return 0;
401}
402
Greg Kurzd815e722017-02-26 23:44:54 +0100403static int local_set_cred_passthrough(FsContext *fs_ctx, int dirfd,
404 const char *name, FsCred *credp)
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700405{
Greg Kurzd815e722017-02-26 23:44:54 +0100406 if (fchownat(dirfd, name, credp->fc_uid, credp->fc_gid,
Greg Kurzb314f6a2017-03-06 17:34:01 +0100407 AT_SYMLINK_NOFOLLOW) < 0) {
Aneesh Kumar K.V12848bf2010-09-02 11:09:07 +0530408 /*
409 * If we fail to change ownership and if we are
410 * using security model none. Ignore the error
411 */
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530412 if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
Greg Kurzd815e722017-02-26 23:44:54 +0100413 return -1;
Aneesh Kumar K.V12848bf2010-09-02 11:09:07 +0530414 }
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700415 }
M. Mohan Kumar2d405642012-01-19 12:21:12 +0530416
Greg Kurzd815e722017-02-26 23:44:54 +0100417 return fchmodat_nofollow(dirfd, name, credp->fc_mode & 07777);
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700418}
419
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530420static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
421 char *buf, size_t bufsz)
Anthony Liguori131dcb22010-04-29 17:44:47 +0530422{
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700423 ssize_t tsize = -1;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530424
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530425 if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
426 (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700427 int fd;
Greg Kurzbec1e952017-02-26 23:43:40 +0100428
429 fd = local_open_nofollow(fs_ctx, fs_path->data, O_RDONLY, 0);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700430 if (fd == -1) {
431 return -1;
432 }
433 do {
434 tsize = read(fd, (void *)buf, bufsz);
435 } while (tsize == -1 && errno == EINTR);
Greg Kurzbec1e952017-02-26 23:43:40 +0100436 close_preserve_errno(fd);
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530437 } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
438 (fs_ctx->export_flags & V9FS_SM_NONE)) {
Greg Kurzbec1e952017-02-26 23:43:40 +0100439 char *dirpath = g_path_get_dirname(fs_path->data);
440 char *name = g_path_get_basename(fs_path->data);
441 int dirfd;
442
443 dirfd = local_opendir_nofollow(fs_ctx, dirpath);
444 if (dirfd == -1) {
445 goto out;
446 }
447
448 tsize = readlinkat(dirfd, name, buf, bufsz);
449 close_preserve_errno(dirfd);
450 out:
451 g_free(name);
452 g_free(dirpath);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700453 }
454 return tsize;
Anthony Liguori131dcb22010-04-29 17:44:47 +0530455}
456
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530457static int local_close(FsContext *ctx, V9fsFidOpenState *fs)
Anthony Liguori131dcb22010-04-29 17:44:47 +0530458{
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530459 return close(fs->fd);
Anthony Liguori131dcb22010-04-29 17:44:47 +0530460}
461
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530462static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
Anthony Liguori131dcb22010-04-29 17:44:47 +0530463{
Greg Kurzf314ea42016-06-06 11:52:34 +0200464 return closedir(fs->dir.stream);
Anthony Liguori131dcb22010-04-29 17:44:47 +0530465}
Anthony Liguori9f107512010-04-29 17:44:44 +0530466
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530467static int local_open(FsContext *ctx, V9fsPath *fs_path,
468 int flags, V9fsFidOpenState *fs)
Anthony Liguoria6568fe2010-04-29 17:44:55 +0530469{
Greg Kurz21328e12017-02-26 23:41:55 +0100470 int fd;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530471
Greg Kurz996a0d72017-02-26 23:42:18 +0100472 fd = local_open_nofollow(ctx, fs_path->data, flags, 0);
Greg Kurz21328e12017-02-26 23:41:55 +0100473 if (fd == -1) {
474 return -1;
475 }
476 fs->fd = fd;
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530477 return fs->fd;
Anthony Liguoria6568fe2010-04-29 17:44:55 +0530478}
479
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530480static int local_opendir(FsContext *ctx,
481 V9fsPath *fs_path, V9fsFidOpenState *fs)
Anthony Liguoria6568fe2010-04-29 17:44:55 +0530482{
Greg Kurz996a0d72017-02-26 23:42:18 +0100483 int dirfd;
Greg Kurz21328e12017-02-26 23:41:55 +0100484 DIR *stream;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530485
Greg Kurz996a0d72017-02-26 23:42:18 +0100486 dirfd = local_opendir_nofollow(ctx, fs_path->data);
487 if (dirfd == -1) {
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530488 return -1;
489 }
Greg Kurz996a0d72017-02-26 23:42:18 +0100490
491 stream = fdopendir(dirfd);
Greg Kurz21328e12017-02-26 23:41:55 +0100492 if (!stream) {
Greg Kurzfaab2072017-03-06 17:34:01 +0100493 close(dirfd);
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530494 return -1;
495 }
Greg Kurz21328e12017-02-26 23:41:55 +0100496 fs->dir.stream = stream;
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530497 return 0;
Anthony Liguoria6568fe2010-04-29 17:44:55 +0530498}
499
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530500static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
Anthony Liguoria9231552010-04-29 17:44:56 +0530501{
Greg Kurzf314ea42016-06-06 11:52:34 +0200502 rewinddir(fs->dir.stream);
Anthony Liguoria9231552010-04-29 17:44:56 +0530503}
504
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530505static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
Anthony Liguoria9231552010-04-29 17:44:56 +0530506{
Greg Kurzf314ea42016-06-06 11:52:34 +0200507 return telldir(fs->dir.stream);
Anthony Liguoria9231552010-04-29 17:44:56 +0530508}
509
Greg Kurz7a954342017-05-05 14:48:08 +0200510static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name)
511{
Greg Kurz81ffbf52017-05-25 10:30:14 +0200512 return
513 !strcmp(name, VIRTFS_META_DIR) || !strcmp(name, VIRTFS_META_ROOT_FILE);
Greg Kurz7a954342017-05-05 14:48:08 +0200514}
515
Greg Kurz635324e2016-06-06 11:52:34 +0200516static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
Anthony Liguoria9231552010-04-29 17:44:56 +0530517{
Greg Kurz635324e2016-06-06 11:52:34 +0200518 struct dirent *entry;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530519
520again:
Greg Kurz635324e2016-06-06 11:52:34 +0200521 entry = readdir(fs->dir.stream);
522 if (!entry) {
523 return NULL;
524 }
525
Bastian Blank840a1bf2014-08-22 13:22:21 +0400526 if (ctx->export_flags & V9FS_SM_MAPPED) {
527 entry->d_type = DT_UNKNOWN;
528 } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Greg Kurz7a954342017-05-05 14:48:08 +0200529 if (local_is_mapped_file_metadata(ctx, entry->d_name)) {
Greg Kurz81ffbf52017-05-25 10:30:14 +0200530 /* skip the meta data */
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530531 goto again;
532 }
Bastian Blank840a1bf2014-08-22 13:22:21 +0400533 entry->d_type = DT_UNKNOWN;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530534 }
Greg Kurz635324e2016-06-06 11:52:34 +0200535
536 return entry;
Anthony Liguoria9231552010-04-29 17:44:56 +0530537}
538
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530539static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
Anthony Liguoria9231552010-04-29 17:44:56 +0530540{
Greg Kurzf314ea42016-06-06 11:52:34 +0200541 seekdir(fs->dir.stream, off);
Anthony Liguoria9231552010-04-29 17:44:56 +0530542}
543
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530544static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
545 const struct iovec *iov,
Sanchit Garg56d15a52010-10-08 11:30:16 +0530546 int iovcnt, off_t offset)
Anthony Liguoria9231552010-04-29 17:44:56 +0530547{
Sanchit Garg56d15a52010-10-08 11:30:16 +0530548#ifdef CONFIG_PREADV
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530549 return preadv(fs->fd, iov, iovcnt, offset);
Sanchit Garg56d15a52010-10-08 11:30:16 +0530550#else
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530551 int err = lseek(fs->fd, offset, SEEK_SET);
Sanchit Garg56d15a52010-10-08 11:30:16 +0530552 if (err == -1) {
553 return err;
554 } else {
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530555 return readv(fs->fd, iov, iovcnt);
Sanchit Garg56d15a52010-10-08 11:30:16 +0530556 }
557#endif
Anthony Liguoria9231552010-04-29 17:44:56 +0530558}
559
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530560static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
561 const struct iovec *iov,
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530562 int iovcnt, off_t offset)
Anthony Liguoria9231552010-04-29 17:44:56 +0530563{
Greg Kurz6fe76ac2017-01-23 09:46:13 +0100564 ssize_t ret;
Sanchit Garg56d15a52010-10-08 11:30:16 +0530565#ifdef CONFIG_PREADV
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530566 ret = pwritev(fs->fd, iov, iovcnt, offset);
Sanchit Garg56d15a52010-10-08 11:30:16 +0530567#else
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530568 int err = lseek(fs->fd, offset, SEEK_SET);
Sanchit Garg56d15a52010-10-08 11:30:16 +0530569 if (err == -1) {
570 return err;
571 } else {
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530572 ret = writev(fs->fd, iov, iovcnt);
Sanchit Garg56d15a52010-10-08 11:30:16 +0530573 }
574#endif
Aneesh Kumar K.Vd3ab98e2011-10-12 19:11:23 +0530575#ifdef CONFIG_SYNC_FILE_RANGE
576 if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
577 /*
578 * Initiate a writeback. This is not a data integrity sync.
579 * We want to ensure that we don't leave dirty pages in the cache
580 * after write when writeout=immediate is sepcified.
581 */
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530582 sync_file_range(fs->fd, offset, ret,
Aneesh Kumar K.Vd3ab98e2011-10-12 19:11:23 +0530583 SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
584 }
585#endif
586 return ret;
Anthony Liguori84493602010-04-29 17:44:58 +0530587}
588
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530589static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530590{
Greg Kurze3187a42017-02-26 23:44:28 +0100591 char *dirpath = g_path_get_dirname(fs_path->data);
592 char *name = g_path_get_basename(fs_path->data);
Chen Gang4fa4ce72014-03-02 01:36:19 +0800593 int ret = -1;
Greg Kurze3187a42017-02-26 23:44:28 +0100594 int dirfd;
595
596 dirfd = local_opendir_nofollow(fs_ctx, dirpath);
597 if (dirfd == -1) {
598 goto out;
599 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530600
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530601 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
Greg Kurze3187a42017-02-26 23:44:28 +0100602 ret = local_set_xattrat(dirfd, name, credp);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530603 } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Greg Kurze3187a42017-02-26 23:44:28 +0100604 ret = local_set_mapped_file_attrat(dirfd, name, credp);
605 } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH ||
606 fs_ctx->export_flags & V9FS_SM_NONE) {
607 ret = fchmodat_nofollow(dirfd, name, credp->fc_mode);
Venkateswararao Jujjuri (JV)e95ead32010-06-14 13:34:42 -0700608 }
Greg Kurze3187a42017-02-26 23:44:28 +0100609 close_preserve_errno(dirfd);
610
611out:
612 g_free(dirpath);
613 g_free(name);
Chen Gang4fa4ce72014-03-02 01:36:19 +0800614 return ret;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530615}
616
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530617static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
618 const char *name, FsCred *credp)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530619{
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700620 int err = -1;
Greg Kurzd815e722017-02-26 23:44:54 +0100621 int dirfd;
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700622
Greg Kurz7a954342017-05-05 14:48:08 +0200623 if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
624 local_is_mapped_file_metadata(fs_ctx, name)) {
625 errno = EINVAL;
626 return -1;
627 }
628
Greg Kurzd815e722017-02-26 23:44:54 +0100629 dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
630 if (dirfd == -1) {
631 return -1;
632 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530633
Greg Kurzd815e722017-02-26 23:44:54 +0100634 if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
635 fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Tobias Schrammb96feb22017-06-29 15:11:50 +0200636 err = mknodat(dirfd, name, fs_ctx->fmode | S_IFREG, 0);
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700637 if (err == -1) {
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530638 goto out;
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700639 }
Greg Kurzd815e722017-02-26 23:44:54 +0100640
641 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
642 err = local_set_xattrat(dirfd, name, credp);
643 } else {
644 err = local_set_mapped_file_attrat(dirfd, name, credp);
645 }
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700646 if (err == -1) {
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700647 goto err_end;
648 }
Greg Kurzd815e722017-02-26 23:44:54 +0100649 } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH ||
650 fs_ctx->export_flags & V9FS_SM_NONE) {
651 err = mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530652 if (err == -1) {
653 goto out;
654 }
Greg Kurzd815e722017-02-26 23:44:54 +0100655 err = local_set_cred_passthrough(fs_ctx, dirfd, name, credp);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530656 if (err == -1) {
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700657 goto err_end;
658 }
659 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530660 goto out;
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700661
662err_end:
Greg Kurzd815e722017-02-26 23:44:54 +0100663 unlinkat_preserve_errno(dirfd, name, 0);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530664out:
Greg Kurzd815e722017-02-26 23:44:54 +0100665 close_preserve_errno(dirfd);
Venkateswararao Jujjuri (JV)1c293312010-06-14 13:34:48 -0700666 return err;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530667}
668
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530669static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
670 const char *name, FsCred *credp)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530671{
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700672 int err = -1;
Greg Kurz3f3a1692017-02-26 23:45:02 +0100673 int dirfd;
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700674
Greg Kurz7a954342017-05-05 14:48:08 +0200675 if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
676 local_is_mapped_file_metadata(fs_ctx, name)) {
677 errno = EINVAL;
678 return -1;
679 }
680
Greg Kurz3f3a1692017-02-26 23:45:02 +0100681 dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
682 if (dirfd == -1) {
683 return -1;
684 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530685
Greg Kurz3f3a1692017-02-26 23:45:02 +0100686 if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
687 fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Tobias Schrammb96feb22017-06-29 15:11:50 +0200688 err = mkdirat(dirfd, name, fs_ctx->dmode);
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700689 if (err == -1) {
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530690 goto out;
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700691 }
Greg Kurz3f3a1692017-02-26 23:45:02 +0100692 credp->fc_mode = credp->fc_mode | S_IFDIR;
693
694 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
695 err = local_set_xattrat(dirfd, name, credp);
696 } else {
697 err = local_set_mapped_file_attrat(dirfd, name, credp);
698 }
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700699 if (err == -1) {
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700700 goto err_end;
701 }
Greg Kurz3f3a1692017-02-26 23:45:02 +0100702 } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH ||
703 fs_ctx->export_flags & V9FS_SM_NONE) {
704 err = mkdirat(dirfd, name, credp->fc_mode);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530705 if (err == -1) {
706 goto out;
707 }
Greg Kurz3f3a1692017-02-26 23:45:02 +0100708 err = local_set_cred_passthrough(fs_ctx, dirfd, name, credp);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530709 if (err == -1) {
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700710 goto err_end;
711 }
712 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530713 goto out;
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700714
715err_end:
Greg Kurz3f3a1692017-02-26 23:45:02 +0100716 unlinkat_preserve_errno(dirfd, name, AT_REMOVEDIR);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530717out:
Greg Kurz3f3a1692017-02-26 23:45:02 +0100718 close_preserve_errno(dirfd);
Venkateswararao Jujjuri (JV)00ec5c32010-06-14 13:34:46 -0700719 return err;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530720}
721
Aneesh Kumar K.V8b888272011-12-04 22:35:28 +0530722static int local_fstat(FsContext *fs_ctx, int fid_type,
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530723 V9fsFidOpenState *fs, struct stat *stbuf)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530724{
Aneesh Kumar K.V8b888272011-12-04 22:35:28 +0530725 int err, fd;
726
727 if (fid_type == P9_FID_DIR) {
Greg Kurzf314ea42016-06-06 11:52:34 +0200728 fd = dirfd(fs->dir.stream);
Aneesh Kumar K.V8b888272011-12-04 22:35:28 +0530729 } else {
730 fd = fs->fd;
731 }
732
733 err = fstat(fd, stbuf);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700734 if (err) {
735 return err;
736 }
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530737 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700738 /* Actual credentials are part of extended attrs */
739 uid_t tmp_uid;
740 gid_t tmp_gid;
741 mode_t tmp_mode;
742 dev_t tmp_dev;
743
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530744 if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
745 stbuf->st_uid = le32_to_cpu(tmp_uid);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700746 }
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530747 if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
748 stbuf->st_gid = le32_to_cpu(tmp_gid);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700749 }
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530750 if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
751 stbuf->st_mode = le32_to_cpu(tmp_mode);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700752 }
Aneesh Kumar K.Vf8ad4a82014-08-03 17:02:55 +0530753 if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
754 stbuf->st_rdev = le64_to_cpu(tmp_dev);
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700755 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530756 } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
757 errno = EOPNOTSUPP;
758 return -1;
Venkateswararao Jujjuri (JV)1237ad72010-06-14 13:34:44 -0700759 }
760 return err;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530761}
762
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530763static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530764 int flags, FsCred *credp, V9fsFidOpenState *fs)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530765{
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700766 int fd = -1;
767 int err = -1;
Greg Kurza565fea2017-02-26 23:45:09 +0100768 int dirfd;
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700769
Greg Kurz7a954342017-05-05 14:48:08 +0200770 if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
771 local_is_mapped_file_metadata(fs_ctx, name)) {
772 errno = EINVAL;
773 return -1;
774 }
775
Aneesh Kumar K.V0ceb0922013-05-20 19:43:15 +0530776 /*
777 * Mark all the open to not follow symlinks
778 */
779 flags |= O_NOFOLLOW;
780
Greg Kurza565fea2017-02-26 23:45:09 +0100781 dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
782 if (dirfd == -1) {
783 return -1;
784 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530785
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700786 /* Determine the security model */
Greg Kurza565fea2017-02-26 23:45:09 +0100787 if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
788 fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Tobias Schrammb96feb22017-06-29 15:11:50 +0200789 fd = openat_file(dirfd, name, flags, fs_ctx->fmode);
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700790 if (fd == -1) {
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530791 goto out;
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700792 }
793 credp->fc_mode = credp->fc_mode|S_IFREG;
Greg Kurza565fea2017-02-26 23:45:09 +0100794 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
795 /* Set cleint credentials in xattr */
796 err = local_set_xattrat(dirfd, name, credp);
797 } else {
798 err = local_set_mapped_file_attrat(dirfd, name, credp);
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700799 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530800 if (err == -1) {
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530801 goto err_end;
802 }
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530803 } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
804 (fs_ctx->export_flags & V9FS_SM_NONE)) {
Greg Kurza565fea2017-02-26 23:45:09 +0100805 fd = openat_file(dirfd, name, flags, credp->fc_mode);
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700806 if (fd == -1) {
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530807 goto out;
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700808 }
Greg Kurza565fea2017-02-26 23:45:09 +0100809 err = local_set_cred_passthrough(fs_ctx, dirfd, name, credp);
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700810 if (err == -1) {
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700811 goto err_end;
812 }
813 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530814 err = fd;
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +0530815 fs->fd = fd;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530816 goto out;
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700817
818err_end:
Greg Kurza565fea2017-02-26 23:45:09 +0100819 unlinkat_preserve_errno(dirfd, name,
820 flags & O_DIRECTORY ? AT_REMOVEDIR : 0);
821 close_preserve_errno(fd);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530822out:
Greg Kurza565fea2017-02-26 23:45:09 +0100823 close_preserve_errno(dirfd);
Venkateswararao Jujjuri (JV)4750a962010-06-14 13:34:45 -0700824 return err;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530825}
826
Venkateswararao Jujjuri (JV)758e8e32010-06-14 13:34:41 -0700827
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700828static int local_symlink(FsContext *fs_ctx, const char *oldpath,
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530829 V9fsPath *dir_path, const char *name, FsCred *credp)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530830{
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700831 int err = -1;
Greg Kurz38771612017-02-26 23:44:46 +0100832 int dirfd;
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700833
Greg Kurz7a954342017-05-05 14:48:08 +0200834 if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
835 local_is_mapped_file_metadata(fs_ctx, name)) {
836 errno = EINVAL;
837 return -1;
838 }
839
Greg Kurz38771612017-02-26 23:44:46 +0100840 dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
841 if (dirfd == -1) {
842 return -1;
843 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530844
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700845 /* Determine the security model */
Greg Kurz38771612017-02-26 23:44:46 +0100846 if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
847 fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700848 int fd;
849 ssize_t oldpath_size, write_size;
Greg Kurz38771612017-02-26 23:44:46 +0100850
851 fd = openat_file(dirfd, name, O_CREAT | O_EXCL | O_RDWR,
Tobias Schrammb96feb22017-06-29 15:11:50 +0200852 fs_ctx->fmode);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700853 if (fd == -1) {
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530854 goto out;
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700855 }
856 /* Write the oldpath (target) to the file. */
Harsh Prateek Boraf35bde22011-02-02 10:20:33 +0530857 oldpath_size = strlen(oldpath);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700858 do {
859 write_size = write(fd, (void *)oldpath, oldpath_size);
860 } while (write_size == -1 && errno == EINTR);
Greg Kurz38771612017-02-26 23:44:46 +0100861 close_preserve_errno(fd);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700862
863 if (write_size != oldpath_size) {
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700864 goto err_end;
865 }
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700866 /* Set cleint credentials in symlink's xattr */
Greg Kurz38771612017-02-26 23:44:46 +0100867 credp->fc_mode = credp->fc_mode | S_IFLNK;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530868
Greg Kurz38771612017-02-26 23:44:46 +0100869 if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
870 err = local_set_xattrat(dirfd, name, credp);
871 } else {
872 err = local_set_mapped_file_attrat(dirfd, name, credp);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530873 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530874 if (err == -1) {
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530875 goto err_end;
876 }
Greg Kurz38771612017-02-26 23:44:46 +0100877 } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH ||
878 fs_ctx->export_flags & V9FS_SM_NONE) {
879 err = symlinkat(oldpath, dirfd, name);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700880 if (err) {
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530881 goto out;
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700882 }
Greg Kurz38771612017-02-26 23:44:46 +0100883 err = fchownat(dirfd, name, credp->fc_uid, credp->fc_gid,
884 AT_SYMLINK_NOFOLLOW);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700885 if (err == -1) {
Aneesh Kumar K.V12848bf2010-09-02 11:09:07 +0530886 /*
887 * If we fail to change ownership and if we are
888 * using security model none. Ignore the error
889 */
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +0530890 if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
Aneesh Kumar K.V12848bf2010-09-02 11:09:07 +0530891 goto err_end;
Greg Kurz38771612017-02-26 23:44:46 +0100892 } else {
Aneesh Kumar K.V12848bf2010-09-02 11:09:07 +0530893 err = 0;
Greg Kurz38771612017-02-26 23:44:46 +0100894 }
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700895 }
896 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530897 goto out;
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700898
899err_end:
Greg Kurz38771612017-02-26 23:44:46 +0100900 unlinkat_preserve_errno(dirfd, name, 0);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530901out:
Greg Kurz38771612017-02-26 23:44:46 +0100902 close_preserve_errno(dirfd);
Venkateswararao Jujjuri (JV)879c2812010-06-14 13:34:47 -0700903 return err;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530904}
905
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530906static int local_link(FsContext *ctx, V9fsPath *oldpath,
907 V9fsPath *dirpath, const char *name)
Anthony Liguoric494dd62010-04-29 17:44:59 +0530908{
Greg Kurzad0b46e2017-02-26 23:44:20 +0100909 char *odirpath = g_path_get_dirname(oldpath->data);
910 char *oname = g_path_get_basename(oldpath->data);
911 int ret = -1;
912 int odirfd, ndirfd;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530913
Greg Kurz7a954342017-05-05 14:48:08 +0200914 if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
915 local_is_mapped_file_metadata(ctx, name)) {
916 errno = EINVAL;
917 return -1;
918 }
919
Greg Kurzad0b46e2017-02-26 23:44:20 +0100920 odirfd = local_opendir_nofollow(ctx, odirpath);
921 if (odirfd == -1) {
Greg Kurz6dd4b1f2017-02-26 23:44:11 +0100922 goto out;
923 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530924
Greg Kurzad0b46e2017-02-26 23:44:20 +0100925 ndirfd = local_opendir_nofollow(ctx, dirpath->data);
926 if (ndirfd == -1) {
927 close_preserve_errno(odirfd);
928 goto out;
929 }
930
931 ret = linkat(odirfd, oname, ndirfd, name, 0);
932 if (ret < 0) {
933 goto out_close;
934 }
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530935
936 /* now link the virtfs_metadata files */
Greg Kurz6dd4b1f2017-02-26 23:44:11 +0100937 if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Greg Kurzad0b46e2017-02-26 23:44:20 +0100938 int omap_dirfd, nmap_dirfd;
Greg Kurz6dd4b1f2017-02-26 23:44:11 +0100939
Greg Kurzad0b46e2017-02-26 23:44:20 +0100940 ret = mkdirat(ndirfd, VIRTFS_META_DIR, 0700);
941 if (ret < 0 && errno != EEXIST) {
942 goto err_undo_link;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530943 }
Greg Kurzad0b46e2017-02-26 23:44:20 +0100944
945 omap_dirfd = openat_dir(odirfd, VIRTFS_META_DIR);
946 if (omap_dirfd == -1) {
947 goto err;
948 }
949
950 nmap_dirfd = openat_dir(ndirfd, VIRTFS_META_DIR);
951 if (nmap_dirfd == -1) {
952 close_preserve_errno(omap_dirfd);
953 goto err;
954 }
955
956 ret = linkat(omap_dirfd, oname, nmap_dirfd, name, 0);
957 close_preserve_errno(nmap_dirfd);
958 close_preserve_errno(omap_dirfd);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530959 if (ret < 0 && errno != ENOENT) {
Greg Kurzad0b46e2017-02-26 23:44:20 +0100960 goto err_undo_link;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530961 }
Greg Kurz6dd4b1f2017-02-26 23:44:11 +0100962
Greg Kurzad0b46e2017-02-26 23:44:20 +0100963 ret = 0;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530964 }
Greg Kurzad0b46e2017-02-26 23:44:20 +0100965 goto out_close;
966
967err:
968 ret = -1;
969err_undo_link:
970 unlinkat_preserve_errno(ndirfd, name, 0);
971out_close:
972 close_preserve_errno(ndirfd);
973 close_preserve_errno(odirfd);
Greg Kurz6dd4b1f2017-02-26 23:44:11 +0100974out:
Greg Kurzad0b46e2017-02-26 23:44:20 +0100975 g_free(oname);
976 g_free(odirpath);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530977 return ret;
Anthony Liguoric494dd62010-04-29 17:44:59 +0530978}
979
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530980static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
Anthony Liguori8cf89e02010-04-29 17:45:00 +0530981{
Greg Kurzac125d92017-02-26 23:43:32 +0100982 int fd, ret;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530983
Greg Kurzac125d92017-02-26 23:43:32 +0100984 fd = local_open_nofollow(ctx, fs_path->data, O_WRONLY, 0);
985 if (fd == -1) {
986 return -1;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +0530987 }
Greg Kurzac125d92017-02-26 23:43:32 +0100988 ret = ftruncate(fd, size);
989 close_preserve_errno(fd);
Anthony Liguoria9231552010-04-29 17:44:56 +0530990 return ret;
Anthony Liguori8cf89e02010-04-29 17:45:00 +0530991}
992
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +0530993static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
Anthony Liguori8cf89e02010-04-29 17:45:00 +0530994{
Greg Kurzd369f202017-02-26 23:44:37 +0100995 char *dirpath = g_path_get_dirname(fs_path->data);
996 char *name = g_path_get_basename(fs_path->data);
Chen Gang4fa4ce72014-03-02 01:36:19 +0800997 int ret = -1;
Greg Kurzd369f202017-02-26 23:44:37 +0100998 int dirfd;
999
1000 dirfd = local_opendir_nofollow(fs_ctx, dirpath);
1001 if (dirfd == -1) {
1002 goto out;
1003 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301004
Sripathi Kodic79ce732010-06-17 18:18:47 +05301005 if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
Aneesh Kumar K.V17b19712011-10-25 12:10:39 +05301006 (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
1007 (fs_ctx->export_flags & V9FS_SM_NONE)) {
Greg Kurzd369f202017-02-26 23:44:37 +01001008 ret = fchownat(dirfd, name, credp->fc_uid, credp->fc_gid,
1009 AT_SYMLINK_NOFOLLOW);
Aneesh Kumar K.Vb97400c2011-10-13 13:21:00 +05301010 } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
Greg Kurzd369f202017-02-26 23:44:37 +01001011 ret = local_set_xattrat(dirfd, name, credp);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301012 } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Greg Kurzd369f202017-02-26 23:44:37 +01001013 ret = local_set_mapped_file_attrat(dirfd, name, credp);
Venkateswararao Jujjuri (JV)f7613be2010-06-14 13:34:43 -07001014 }
Greg Kurzd369f202017-02-26 23:44:37 +01001015
1016 close_preserve_errno(dirfd);
1017out:
1018 g_free(name);
1019 g_free(dirpath);
Chen Gang4fa4ce72014-03-02 01:36:19 +08001020 return ret;
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301021}
1022
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301023static int local_utimensat(FsContext *s, V9fsPath *fs_path,
Hidetoshi Seto38671422010-11-24 11:38:10 +09001024 const struct timespec *buf)
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301025{
Greg Kurza33eda02017-02-26 23:43:17 +01001026 char *dirpath = g_path_get_dirname(fs_path->data);
1027 char *name = g_path_get_basename(fs_path->data);
1028 int dirfd, ret = -1;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301029
Greg Kurza33eda02017-02-26 23:43:17 +01001030 dirfd = local_opendir_nofollow(s, dirpath);
1031 if (dirfd == -1) {
1032 goto out;
1033 }
1034
1035 ret = utimensat(dirfd, name, buf, AT_SYMLINK_NOFOLLOW);
1036 close_preserve_errno(dirfd);
1037out:
1038 g_free(dirpath);
1039 g_free(name);
Chen Gang4fa4ce72014-03-02 01:36:19 +08001040 return ret;
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301041}
1042
Greg Kurzdf4938a2017-02-26 23:43:00 +01001043static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
1044 int flags)
Anthony Liguori5bae1902010-04-29 17:45:01 +05301045{
Greg Kurzdf4938a2017-02-26 23:43:00 +01001046 int ret = -1;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301047
1048 if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
Greg Kurzdf4938a2017-02-26 23:43:00 +01001049 int map_dirfd;
1050
Greg Kurz6a87e792017-05-25 10:30:13 +02001051 /* We need to remove the metadata as well:
1052 * - the metadata directory if we're removing a directory
1053 * - the metadata file in the parent's metadata directory
1054 *
1055 * If any of these are missing (ie, ENOENT) then we're probably
1056 * trying to remove something that wasn't created in mapped-file
1057 * mode. We just ignore the error.
1058 */
Greg Kurzdf4938a2017-02-26 23:43:00 +01001059 if (flags == AT_REMOVEDIR) {
1060 int fd;
1061
Greg Kurzb003fc02017-03-06 17:34:01 +01001062 fd = openat_dir(dirfd, name);
Greg Kurzdf4938a2017-02-26 23:43:00 +01001063 if (fd == -1) {
1064 goto err_out;
1065 }
Greg Kurzdf4938a2017-02-26 23:43:00 +01001066 ret = unlinkat(fd, VIRTFS_META_DIR, AT_REMOVEDIR);
1067 close_preserve_errno(fd);
1068 if (ret < 0 && errno != ENOENT) {
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301069 goto err_out;
1070 }
1071 }
Greg Kurzdf4938a2017-02-26 23:43:00 +01001072 map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR);
Greg Kurz6a87e792017-05-25 10:30:13 +02001073 if (map_dirfd != -1) {
1074 ret = unlinkat(map_dirfd, name, 0);
1075 close_preserve_errno(map_dirfd);
1076 if (ret < 0 && errno != ENOENT) {
1077 goto err_out;
1078 }
1079 } else if (errno != ENOENT) {
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301080 goto err_out;
1081 }
1082 }
Chen Gang4fa4ce72014-03-02 01:36:19 +08001083
Greg Kurzdf4938a2017-02-26 23:43:00 +01001084 ret = unlinkat(dirfd, name, flags);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301085err_out:
Greg Kurzdf4938a2017-02-26 23:43:00 +01001086 return ret;
1087}
1088
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301089static int local_remove(FsContext *ctx, const char *path)
1090{
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301091 struct stat stbuf;
Greg Kurza0e640a2017-02-26 23:43:08 +01001092 char *dirpath = g_path_get_dirname(path);
1093 char *name = g_path_get_basename(path);
1094 int flags = 0;
1095 int dirfd;
1096 int err = -1;
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301097
Greg Kurza0e640a2017-02-26 23:43:08 +01001098 dirfd = local_opendir_nofollow(ctx, dirpath);
Greg Kurzb7361d42017-03-06 17:34:01 +01001099 if (dirfd == -1) {
Greg Kurza0e640a2017-02-26 23:43:08 +01001100 goto out;
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301101 }
Anthony Liguori5bae1902010-04-29 17:45:01 +05301102
Bruce Rogers790db7e2017-06-29 15:11:50 +02001103 if (fstatat(dirfd, name, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) {
Greg Kurza0e640a2017-02-26 23:43:08 +01001104 goto err_out;
1105 }
1106
1107 if (S_ISDIR(stbuf.st_mode)) {
1108 flags |= AT_REMOVEDIR;
1109 }
1110
1111 err = local_unlinkat_common(ctx, dirfd, name, flags);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301112err_out:
Greg Kurza0e640a2017-02-26 23:43:08 +01001113 close_preserve_errno(dirfd);
1114out:
1115 g_free(name);
1116 g_free(dirpath);
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301117 return err;
Anthony Liguori5bae1902010-04-29 17:45:01 +05301118}
1119
Aneesh Kumar K.V8b888272011-12-04 22:35:28 +05301120static int local_fsync(FsContext *ctx, int fid_type,
1121 V9fsFidOpenState *fs, int datasync)
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301122{
Aneesh Kumar K.V8b888272011-12-04 22:35:28 +05301123 int fd;
1124
1125 if (fid_type == P9_FID_DIR) {
Greg Kurzf314ea42016-06-06 11:52:34 +02001126 fd = dirfd(fs->dir.stream);
Venkateswararao Jujjuri (JV)49594972010-10-22 10:08:45 -07001127 } else {
Aneesh Kumar K.V8b888272011-12-04 22:35:28 +05301128 fd = fs->fd;
1129 }
1130
1131 if (datasync) {
1132 return qemu_fdatasync(fd);
1133 } else {
1134 return fsync(fd);
Venkateswararao Jujjuri (JV)49594972010-10-22 10:08:45 -07001135 }
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301136}
1137
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301138static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
M. Mohan Kumarbe940c82010-05-10 12:11:03 +05301139{
Greg Kurz31e51d12017-02-26 23:43:25 +01001140 int fd, ret;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301141
Greg Kurz31e51d12017-02-26 23:43:25 +01001142 fd = local_open_nofollow(s, fs_path->data, O_RDONLY, 0);
Greg Kurz23da0142017-03-06 17:34:01 +01001143 if (fd == -1) {
1144 return -1;
1145 }
Greg Kurz31e51d12017-02-26 23:43:25 +01001146 ret = fstatfs(fd, stbuf);
1147 close_preserve_errno(fd);
Chen Gang4fa4ce72014-03-02 01:36:19 +08001148 return ret;
M. Mohan Kumarbe940c82010-05-10 12:11:03 +05301149}
1150
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301151static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
Aneesh Kumar K.Vfa32ef82010-09-02 11:09:06 +05301152 const char *name, void *value, size_t size)
1153{
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301154 char *path = fs_path->data;
1155
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +05301156 return v9fs_get_xattr(ctx, path, name, value, size);
Aneesh Kumar K.Vfa32ef82010-09-02 11:09:06 +05301157}
1158
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301159static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
Aneesh Kumar K.Vfa32ef82010-09-02 11:09:06 +05301160 void *value, size_t size)
1161{
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301162 char *path = fs_path->data;
1163
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +05301164 return v9fs_list_xattr(ctx, path, value, size);
Aneesh Kumar K.Vfa32ef82010-09-02 11:09:06 +05301165}
1166
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301167static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
Aneesh Kumar K.V10b468b2010-09-02 11:09:07 +05301168 void *value, size_t size, int flags)
1169{
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301170 char *path = fs_path->data;
1171
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +05301172 return v9fs_set_xattr(ctx, path, name, value, size, flags);
Aneesh Kumar K.V10b468b2010-09-02 11:09:07 +05301173}
1174
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301175static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
1176 const char *name)
Aneesh Kumar K.V9ed3ef22010-08-26 11:15:23 +05301177{
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301178 char *path = fs_path->data;
1179
Aneesh Kumar K.Vfc221182010-10-18 15:28:16 +05301180 return v9fs_remove_xattr(ctx, path, name);
Aneesh Kumar K.V9ed3ef22010-08-26 11:15:23 +05301181}
1182
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301183static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
1184 const char *name, V9fsPath *target)
1185{
Greg Kurz7a954342017-05-05 14:48:08 +02001186 if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
1187 local_is_mapped_file_metadata(ctx, name)) {
1188 errno = EINVAL;
1189 return -1;
1190 }
1191
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301192 if (dir_path) {
Greg Kurzf57f5872017-05-25 10:30:14 +02001193 if (!strcmp(name, ".")) {
1194 /* "." relative to "foo/bar" is "foo/bar" */
1195 v9fs_path_copy(target, dir_path);
1196 } else if (!strcmp(name, "..")) {
1197 if (!strcmp(dir_path->data, ".")) {
1198 /* ".." relative to the root is "." */
1199 v9fs_path_sprintf(target, ".");
1200 } else {
1201 char *tmp = g_path_get_dirname(dir_path->data);
1202 /* Symbolic links are resolved by the client. We can assume
1203 * that ".." relative to "foo/bar" is equivalent to "foo"
1204 */
1205 v9fs_path_sprintf(target, "%s", tmp);
1206 g_free(tmp);
1207 }
1208 } else {
1209 assert(!strchr(name, '/'));
1210 v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
1211 }
1212 } else if (!strcmp(name, "/") || !strcmp(name, ".") ||
1213 !strcmp(name, "..")) {
1214 /* This is the root fid */
1215 v9fs_path_sprintf(target, ".");
Greg Kurz9c6b8992017-04-17 10:53:23 +02001216 } else {
Greg Kurzf57f5872017-05-25 10:30:14 +02001217 assert(!strchr(name, '/'));
1218 v9fs_path_sprintf(target, "./%s", name);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301219 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301220 return 0;
1221}
1222
1223static int local_renameat(FsContext *ctx, V9fsPath *olddir,
1224 const char *old_name, V9fsPath *newdir,
1225 const char *new_name)
1226{
1227 int ret;
Greg Kurz99f2cf42017-02-26 23:43:55 +01001228 int odirfd, ndirfd;
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301229
Greg Kurz7a954342017-05-05 14:48:08 +02001230 if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
1231 (local_is_mapped_file_metadata(ctx, old_name) ||
1232 local_is_mapped_file_metadata(ctx, new_name))) {
1233 errno = EINVAL;
1234 return -1;
1235 }
1236
Greg Kurz99f2cf42017-02-26 23:43:55 +01001237 odirfd = local_opendir_nofollow(ctx, olddir->data);
1238 if (odirfd == -1) {
1239 return -1;
1240 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301241
Greg Kurz99f2cf42017-02-26 23:43:55 +01001242 ndirfd = local_opendir_nofollow(ctx, newdir->data);
1243 if (ndirfd == -1) {
1244 close_preserve_errno(odirfd);
1245 return -1;
1246 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301247
Greg Kurz99f2cf42017-02-26 23:43:55 +01001248 ret = renameat(odirfd, old_name, ndirfd, new_name);
1249 if (ret < 0) {
1250 goto out;
1251 }
1252
1253 if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
1254 int omap_dirfd, nmap_dirfd;
1255
1256 ret = mkdirat(ndirfd, VIRTFS_META_DIR, 0700);
1257 if (ret < 0 && errno != EEXIST) {
1258 goto err_undo_rename;
1259 }
1260
Greg Kurz6dd4b1f2017-02-26 23:44:11 +01001261 omap_dirfd = openat_dir(odirfd, VIRTFS_META_DIR);
Greg Kurz99f2cf42017-02-26 23:43:55 +01001262 if (omap_dirfd == -1) {
1263 goto err;
1264 }
1265
Greg Kurz6dd4b1f2017-02-26 23:44:11 +01001266 nmap_dirfd = openat_dir(ndirfd, VIRTFS_META_DIR);
Greg Kurz99f2cf42017-02-26 23:43:55 +01001267 if (nmap_dirfd == -1) {
1268 close_preserve_errno(omap_dirfd);
1269 goto err;
1270 }
1271
1272 /* rename the .virtfs_metadata files */
1273 ret = renameat(omap_dirfd, old_name, nmap_dirfd, new_name);
1274 close_preserve_errno(nmap_dirfd);
1275 close_preserve_errno(omap_dirfd);
1276 if (ret < 0 && errno != ENOENT) {
1277 goto err_undo_rename;
1278 }
1279
1280 ret = 0;
1281 }
1282 goto out;
1283
1284err:
1285 ret = -1;
1286err_undo_rename:
1287 renameat_preserve_errno(ndirfd, new_name, odirfd, old_name);
1288out:
1289 close_preserve_errno(ndirfd);
1290 close_preserve_errno(odirfd);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301291 return ret;
1292}
1293
Greg Kurzd2767ed2017-02-26 23:44:03 +01001294static void v9fs_path_init_dirname(V9fsPath *path, const char *str)
1295{
1296 path->data = g_path_get_dirname(str);
1297 path->size = strlen(path->data) + 1;
1298}
1299
1300static int local_rename(FsContext *ctx, const char *oldpath,
1301 const char *newpath)
1302{
1303 int err;
1304 char *oname = g_path_get_basename(oldpath);
1305 char *nname = g_path_get_basename(newpath);
1306 V9fsPath olddir, newdir;
1307
1308 v9fs_path_init_dirname(&olddir, oldpath);
1309 v9fs_path_init_dirname(&newdir, newpath);
1310
1311 err = local_renameat(ctx, &olddir, oname, &newdir, nname);
1312
1313 v9fs_path_free(&newdir);
1314 v9fs_path_free(&olddir);
1315 g_free(nname);
1316 g_free(oname);
1317
1318 return err;
1319}
1320
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301321static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
1322 const char *name, int flags)
1323{
1324 int ret;
Greg Kurzdf4938a2017-02-26 23:43:00 +01001325 int dirfd;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301326
Greg Kurz7a954342017-05-05 14:48:08 +02001327 if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
1328 local_is_mapped_file_metadata(ctx, name)) {
1329 errno = EINVAL;
1330 return -1;
1331 }
1332
Greg Kurzdf4938a2017-02-26 23:43:00 +01001333 dirfd = local_opendir_nofollow(ctx, dir->data);
1334 if (dirfd == -1) {
1335 return -1;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301336 }
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301337
Greg Kurzdf4938a2017-02-26 23:43:00 +01001338 ret = local_unlinkat_common(ctx, dirfd, name, flags);
1339 close_preserve_errno(dirfd);
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301340 return ret;
1341}
Aneesh Kumar K.V9ed3ef22010-08-26 11:15:23 +05301342
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301343static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
1344 mode_t st_mode, uint64_t *st_gen)
1345{
Paolo Bonziniae0f9402011-11-21 09:29:11 +01001346#ifdef FS_IOC_GETVERSION
Kirill A. Shutemov0e5fc992014-01-28 17:08:24 +02001347 int err;
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +05301348 V9fsFidOpenState fid_open;
1349
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301350 /*
1351 * Do not try to open special files like device nodes, fifos etc
1352 * We can get fd for regular files and directories only
1353 */
1354 if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
Kirill A. Shutemov1a9978a2014-01-28 17:08:26 +02001355 errno = ENOTTY;
1356 return -1;
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301357 }
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +05301358 err = local_open(ctx, path, O_RDONLY, &fid_open);
1359 if (err < 0) {
1360 return err;
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301361 }
Aneesh Kumar K.Vcc720dd2011-10-25 12:10:40 +05301362 err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
1363 local_close(ctx, &fid_open);
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301364 return err;
Kirill A. Shutemov0e5fc992014-01-28 17:08:24 +02001365#else
1366 errno = ENOTTY;
1367 return -1;
1368#endif
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301369}
1370
Aneesh Kumar K.V0174fe72011-08-02 11:35:54 +05301371static int local_init(FsContext *ctx)
1372{
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301373 struct statfs stbuf;
Greg Kurz0e35a372017-02-26 23:42:10 +01001374 LocalData *data = g_malloc(sizeof(*data));
1375
1376 data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY);
1377 if (data->mountfd == -1) {
1378 goto err;
1379 }
Harsh Prateek Borae06a7652011-10-12 19:11:25 +05301380
Greg Kurz00c90bd2017-02-26 23:41:48 +01001381#ifdef FS_IOC_GETVERSION
1382 /*
1383 * use ioc_getversion only if the ioctl is definied
1384 */
Greg Kurz0e35a372017-02-26 23:42:10 +01001385 if (fstatfs(data->mountfd, &stbuf) < 0) {
1386 close_preserve_errno(data->mountfd);
1387 goto err;
Greg Kurz00c90bd2017-02-26 23:41:48 +01001388 }
1389 switch (stbuf.f_type) {
1390 case EXT2_SUPER_MAGIC:
1391 case BTRFS_SUPER_MAGIC:
1392 case REISERFS_SUPER_MAGIC:
1393 case XFS_SUPER_MAGIC:
1394 ctx->exops.get_st_gen = local_ioc_getversion;
1395 break;
1396 }
1397#endif
Aneesh Kumar K.V0174fe72011-08-02 11:35:54 +05301398
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301399 if (ctx->export_flags & V9FS_SM_PASSTHROUGH) {
1400 ctx->xops = passthrough_xattr_ops;
1401 } else if (ctx->export_flags & V9FS_SM_MAPPED) {
1402 ctx->xops = mapped_xattr_ops;
1403 } else if (ctx->export_flags & V9FS_SM_NONE) {
1404 ctx->xops = none_xattr_ops;
1405 } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
1406 /*
1407 * xattr operation for mapped-file and passthrough
1408 * remain same.
1409 */
1410 ctx->xops = passthrough_xattr_ops;
1411 }
Aneesh Kumar K.Vc98f1d42011-10-12 20:59:18 +05301412 ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
Greg Kurz00c90bd2017-02-26 23:41:48 +01001413
Greg Kurz0e35a372017-02-26 23:42:10 +01001414 ctx->private = data;
Greg Kurz00c90bd2017-02-26 23:41:48 +01001415 return 0;
Greg Kurz0e35a372017-02-26 23:42:10 +01001416
1417err:
1418 g_free(data);
1419 return -1;
1420}
1421
1422static void local_cleanup(FsContext *ctx)
1423{
1424 LocalData *data = ctx->private;
1425
1426 close(data->mountfd);
1427 g_free(data);
Aneesh Kumar K.V0174fe72011-08-02 11:35:54 +05301428}
1429
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301430static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
1431{
1432 const char *sec_model = qemu_opt_get(opts, "security_model");
1433 const char *path = qemu_opt_get(opts, "path");
Pradeep Jagadeeshb8bbdb82017-02-28 10:31:46 +01001434 Error *err = NULL;
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301435
1436 if (!sec_model) {
Greg Kurz63325b12016-01-22 15:12:17 +01001437 error_report("Security model not specified, local fs needs security model");
1438 error_printf("valid options are:"
1439 "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n");
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301440 return -1;
1441 }
1442
1443 if (!strcmp(sec_model, "passthrough")) {
1444 fse->export_flags |= V9FS_SM_PASSTHROUGH;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301445 } else if (!strcmp(sec_model, "mapped") ||
1446 !strcmp(sec_model, "mapped-xattr")) {
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301447 fse->export_flags |= V9FS_SM_MAPPED;
1448 } else if (!strcmp(sec_model, "none")) {
1449 fse->export_flags |= V9FS_SM_NONE;
Aneesh Kumar K.V2c30dd72012-01-19 12:21:11 +05301450 } else if (!strcmp(sec_model, "mapped-file")) {
1451 fse->export_flags |= V9FS_SM_MAPPED_FILE;
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301452 } else {
Greg Kurz63325b12016-01-22 15:12:17 +01001453 error_report("Invalid security model %s specified", sec_model);
1454 error_printf("valid options are:"
1455 "\t[passthrough|mapped-xattr|mapped-file|none]\n");
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301456 return -1;
1457 }
1458
1459 if (!path) {
Greg Kurz63325b12016-01-22 15:12:17 +01001460 error_report("fsdev: No path specified");
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301461 return -1;
1462 }
Pradeep Jagadeeshb8bbdb82017-02-28 10:31:46 +01001463
1464 fsdev_throttle_parse_opts(opts, &fse->fst, &err);
1465 if (err) {
1466 error_reportf_err(err, "Throttle configuration is not valid: ");
1467 return -1;
1468 }
1469
Tobias Schrammb96feb22017-06-29 15:11:50 +02001470 if (fse->export_flags & V9FS_SM_MAPPED ||
1471 fse->export_flags & V9FS_SM_MAPPED_FILE) {
1472 fse->fmode =
1473 qemu_opt_get_number(opts, "fmode", SM_LOCAL_MODE_BITS) & 0777;
1474 fse->dmode =
1475 qemu_opt_get_number(opts, "dmode", SM_LOCAL_DIR_MODE_BITS) & 0777;
1476 } else {
1477 if (qemu_opt_find(opts, "fmode")) {
1478 error_report("fmode is only valid for mapped 9p modes");
1479 return -1;
1480 }
1481 if (qemu_opt_find(opts, "dmode")) {
1482 error_report("dmode is only valid for mapped 9p modes");
1483 return -1;
1484 }
1485 }
1486
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301487 fse->path = g_strdup(path);
1488
1489 return 0;
1490}
1491
Anthony Liguori9f107512010-04-29 17:44:44 +05301492FileOperations local_ops = {
Aneesh Kumar K.V99519f02011-12-14 13:48:59 +05301493 .parse_opts = local_parse_opts,
Aneesh Kumar K.V0174fe72011-08-02 11:35:54 +05301494 .init = local_init,
Greg Kurz0e35a372017-02-26 23:42:10 +01001495 .cleanup = local_cleanup,
Anthony Liguori131dcb22010-04-29 17:44:47 +05301496 .lstat = local_lstat,
Anthony Liguori131dcb22010-04-29 17:44:47 +05301497 .readlink = local_readlink,
1498 .close = local_close,
1499 .closedir = local_closedir,
Anthony Liguoria6568fe2010-04-29 17:44:55 +05301500 .open = local_open,
1501 .opendir = local_opendir,
Anthony Liguoria9231552010-04-29 17:44:56 +05301502 .rewinddir = local_rewinddir,
1503 .telldir = local_telldir,
Greg Kurz635324e2016-06-06 11:52:34 +02001504 .readdir = local_readdir,
Anthony Liguoria9231552010-04-29 17:44:56 +05301505 .seekdir = local_seekdir,
Sanchit Garg56d15a52010-10-08 11:30:16 +05301506 .preadv = local_preadv,
1507 .pwritev = local_pwritev,
Anthony Liguoric494dd62010-04-29 17:44:59 +05301508 .chmod = local_chmod,
1509 .mknod = local_mknod,
Anthony Liguoric494dd62010-04-29 17:44:59 +05301510 .mkdir = local_mkdir,
1511 .fstat = local_fstat,
1512 .open2 = local_open2,
1513 .symlink = local_symlink,
1514 .link = local_link,
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301515 .truncate = local_truncate,
1516 .rename = local_rename,
1517 .chown = local_chown,
M. Mohan Kumar74bc02b2010-06-09 19:14:38 +05301518 .utimensat = local_utimensat,
Anthony Liguori5bae1902010-04-29 17:45:01 +05301519 .remove = local_remove,
Anthony Liguori8cf89e02010-04-29 17:45:00 +05301520 .fsync = local_fsync,
M. Mohan Kumarbe940c82010-05-10 12:11:03 +05301521 .statfs = local_statfs,
Aneesh Kumar K.Vfa32ef82010-09-02 11:09:06 +05301522 .lgetxattr = local_lgetxattr,
1523 .llistxattr = local_llistxattr,
Aneesh Kumar K.V10b468b2010-09-02 11:09:07 +05301524 .lsetxattr = local_lsetxattr,
Aneesh Kumar K.V9ed3ef22010-08-26 11:15:23 +05301525 .lremovexattr = local_lremovexattr,
Aneesh Kumar K.V2289be12011-09-09 15:14:18 +05301526 .name_to_path = local_name_to_path,
1527 .renameat = local_renameat,
1528 .unlinkat = local_unlinkat,
Anthony Liguori9f107512010-04-29 17:44:44 +05301529};