linux/fs/9p/vfs_inode_dotl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * This file contains vfs inode ops for the 9P2000.L protocol.
   4 *
   5 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
   6 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/errno.h>
  11#include <linux/fs.h>
  12#include <linux/file.h>
  13#include <linux/pagemap.h>
  14#include <linux/stat.h>
  15#include <linux/string.h>
  16#include <linux/inet.h>
  17#include <linux/namei.h>
  18#include <linux/idr.h>
  19#include <linux/sched.h>
  20#include <linux/slab.h>
  21#include <linux/xattr.h>
  22#include <linux/posix_acl.h>
  23#include <net/9p/9p.h>
  24#include <net/9p/client.h>
  25
  26#include "v9fs.h"
  27#include "v9fs_vfs.h"
  28#include "fid.h"
  29#include "cache.h"
  30#include "xattr.h"
  31#include "acl.h"
  32
  33static int
  34v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
  35                    struct dentry *dentry, umode_t omode, dev_t rdev);
  36
  37/**
  38 * v9fs_get_fsgid_for_create - Helper function to get the gid for a new object
  39 * @dir_inode: The directory inode
  40 *
  41 * Helper function to get the gid for creating a
  42 * new file system object. This checks the S_ISGID to determine the owning
  43 * group of the new file system object.
  44 */
  45
  46static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
  47{
  48        BUG_ON(dir_inode == NULL);
  49
  50        if (dir_inode->i_mode & S_ISGID) {
  51                /* set_gid bit is set.*/
  52                return dir_inode->i_gid;
  53        }
  54        return current_fsgid();
  55}
  56
  57static int v9fs_test_inode_dotl(struct inode *inode, void *data)
  58{
  59        struct v9fs_inode *v9inode = V9FS_I(inode);
  60        struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
  61
  62        /* don't match inode of different type */
  63        if (inode_wrong_type(inode, st->st_mode))
  64                return 0;
  65
  66        if (inode->i_generation != st->st_gen)
  67                return 0;
  68
  69        /* compare qid details */
  70        if (memcmp(&v9inode->qid.version,
  71                   &st->qid.version, sizeof(v9inode->qid.version)))
  72                return 0;
  73
  74        if (v9inode->qid.type != st->qid.type)
  75                return 0;
  76
  77        if (v9inode->qid.path != st->qid.path)
  78                return 0;
  79        return 1;
  80}
  81
  82/* Always get a new inode */
  83static int v9fs_test_new_inode_dotl(struct inode *inode, void *data)
  84{
  85        return 0;
  86}
  87
  88static int v9fs_set_inode_dotl(struct inode *inode,  void *data)
  89{
  90        struct v9fs_inode *v9inode = V9FS_I(inode);
  91        struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
  92
  93        memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
  94        inode->i_generation = st->st_gen;
  95        return 0;
  96}
  97
  98static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
  99                                        struct p9_qid *qid,
 100                                        struct p9_fid *fid,
 101                                        struct p9_stat_dotl *st,
 102                                        int new)
 103{
 104        int retval;
 105        unsigned long i_ino;
 106        struct inode *inode;
 107        struct v9fs_session_info *v9ses = sb->s_fs_info;
 108        int (*test)(struct inode *inode, void *data);
 109
 110        if (new)
 111                test = v9fs_test_new_inode_dotl;
 112        else
 113                test = v9fs_test_inode_dotl;
 114
 115        i_ino = v9fs_qid2ino(qid);
 116        inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
 117        if (!inode)
 118                return ERR_PTR(-ENOMEM);
 119        if (!(inode->i_state & I_NEW))
 120                return inode;
 121        /*
 122         * initialize the inode with the stat info
 123         * FIXME!! we may need support for stale inodes
 124         * later.
 125         */
 126        inode->i_ino = i_ino;
 127        retval = v9fs_init_inode(v9ses, inode,
 128                                 st->st_mode, new_decode_dev(st->st_rdev));
 129        if (retval)
 130                goto error;
 131
 132        v9fs_stat2inode_dotl(st, inode, 0);
 133        v9fs_cache_inode_get_cookie(inode);
 134        retval = v9fs_get_acl(inode, fid);
 135        if (retval)
 136                goto error;
 137
 138        unlock_new_inode(inode);
 139        return inode;
 140error:
 141        iget_failed(inode);
 142        return ERR_PTR(retval);
 143
 144}
 145
 146struct inode *
 147v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 148                         struct super_block *sb, int new)
 149{
 150        struct p9_stat_dotl *st;
 151        struct inode *inode = NULL;
 152
 153        st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN);
 154        if (IS_ERR(st))
 155                return ERR_CAST(st);
 156
 157        inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new);
 158        kfree(st);
 159        return inode;
 160}
 161
 162struct dotl_openflag_map {
 163        int open_flag;
 164        int dotl_flag;
 165};
 166
 167static int v9fs_mapped_dotl_flags(int flags)
 168{
 169        int i;
 170        int rflags = 0;
 171        struct dotl_openflag_map dotl_oflag_map[] = {
 172                { O_CREAT,      P9_DOTL_CREATE },
 173                { O_EXCL,       P9_DOTL_EXCL },
 174                { O_NOCTTY,     P9_DOTL_NOCTTY },
 175                { O_APPEND,     P9_DOTL_APPEND },
 176                { O_NONBLOCK,   P9_DOTL_NONBLOCK },
 177                { O_DSYNC,      P9_DOTL_DSYNC },
 178                { FASYNC,       P9_DOTL_FASYNC },
 179                { O_DIRECT,     P9_DOTL_DIRECT },
 180                { O_LARGEFILE,  P9_DOTL_LARGEFILE },
 181                { O_DIRECTORY,  P9_DOTL_DIRECTORY },
 182                { O_NOFOLLOW,   P9_DOTL_NOFOLLOW },
 183                { O_NOATIME,    P9_DOTL_NOATIME },
 184                { O_CLOEXEC,    P9_DOTL_CLOEXEC },
 185                { O_SYNC,       P9_DOTL_SYNC},
 186        };
 187        for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
 188                if (flags & dotl_oflag_map[i].open_flag)
 189                        rflags |= dotl_oflag_map[i].dotl_flag;
 190        }
 191        return rflags;
 192}
 193
 194/**
 195 * v9fs_open_to_dotl_flags- convert Linux specific open flags to
 196 * plan 9 open flag.
 197 * @flags: flags to convert
 198 */
 199int v9fs_open_to_dotl_flags(int flags)
 200{
 201        int rflags = 0;
 202
 203        /*
 204         * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
 205         * and P9_DOTL_NOACCESS
 206         */
 207        rflags |= flags & O_ACCMODE;
 208        rflags |= v9fs_mapped_dotl_flags(flags);
 209
 210        return rflags;
 211}
 212
 213/**
 214 * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
 215 * @mnt_userns: The user namespace of the mount
 216 * @dir: directory inode that is being created
 217 * @dentry:  dentry that is being deleted
 218 * @omode: create permissions
 219 * @excl: True if the file must not yet exist
 220 *
 221 */
 222static int
 223v9fs_vfs_create_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 224                     struct dentry *dentry, umode_t omode, bool excl)
 225{
 226        return v9fs_vfs_mknod_dotl(mnt_userns, dir, dentry, omode, 0);
 227}
 228
 229static int
 230v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 231                          struct file *file, unsigned int flags, umode_t omode)
 232{
 233        int err = 0;
 234        kgid_t gid;
 235        umode_t mode;
 236        const unsigned char *name = NULL;
 237        struct p9_qid qid;
 238        struct inode *inode;
 239        struct p9_fid *fid = NULL;
 240        struct v9fs_inode *v9inode;
 241        struct p9_fid *dfid, *ofid, *inode_fid;
 242        struct v9fs_session_info *v9ses;
 243        struct posix_acl *pacl = NULL, *dacl = NULL;
 244        struct dentry *res = NULL;
 245
 246        if (d_in_lookup(dentry)) {
 247                res = v9fs_vfs_lookup(dir, dentry, 0);
 248                if (IS_ERR(res))
 249                        return PTR_ERR(res);
 250
 251                if (res)
 252                        dentry = res;
 253        }
 254
 255        /* Only creates */
 256        if (!(flags & O_CREAT) || d_really_is_positive(dentry))
 257                return  finish_no_open(file, res);
 258
 259        v9ses = v9fs_inode2v9ses(dir);
 260
 261        name = dentry->d_name.name;
 262        p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%x\n",
 263                 name, flags, omode);
 264
 265        dfid = v9fs_parent_fid(dentry);
 266        if (IS_ERR(dfid)) {
 267                err = PTR_ERR(dfid);
 268                p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
 269                goto out;
 270        }
 271
 272        /* clone a fid to use for creation */
 273        ofid = clone_fid(dfid);
 274        if (IS_ERR(ofid)) {
 275                err = PTR_ERR(ofid);
 276                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
 277                goto out;
 278        }
 279
 280        gid = v9fs_get_fsgid_for_create(dir);
 281
 282        mode = omode;
 283        /* Update mode based on ACL value */
 284        err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
 285        if (err) {
 286                p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
 287                         err);
 288                goto error;
 289        }
 290        err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
 291                                    mode, gid, &qid);
 292        if (err < 0) {
 293                p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
 294                         err);
 295                goto error;
 296        }
 297        v9fs_invalidate_inode_attr(dir);
 298
 299        /* instantiate inode and assign the unopened fid to the dentry */
 300        fid = p9_client_walk(dfid, 1, &name, 1);
 301        p9_client_clunk(dfid);
 302        if (IS_ERR(fid)) {
 303                err = PTR_ERR(fid);
 304                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
 305                fid = NULL;
 306                goto error;
 307        }
 308        inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 309        if (IS_ERR(inode)) {
 310                err = PTR_ERR(inode);
 311                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
 312                goto error;
 313        }
 314        /* Now set the ACL based on the default value */
 315        v9fs_set_create_acl(inode, fid, dacl, pacl);
 316
 317        v9fs_fid_add(dentry, fid);
 318        d_instantiate(dentry, inode);
 319
 320        v9inode = V9FS_I(inode);
 321        mutex_lock(&v9inode->v_mutex);
 322        if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
 323            !v9inode->writeback_fid &&
 324            ((flags & O_ACCMODE) != O_RDONLY)) {
 325                /*
 326                 * clone a fid and add it to writeback_fid
 327                 * we do it during open time instead of
 328                 * page dirty time via write_begin/page_mkwrite
 329                 * because we want write after unlink usecase
 330                 * to work.
 331                 */
 332                inode_fid = v9fs_writeback_fid(dentry);
 333                if (IS_ERR(inode_fid)) {
 334                        err = PTR_ERR(inode_fid);
 335                        mutex_unlock(&v9inode->v_mutex);
 336                        goto err_clunk_old_fid;
 337                }
 338                v9inode->writeback_fid = (void *) inode_fid;
 339        }
 340        mutex_unlock(&v9inode->v_mutex);
 341        /* Since we are opening a file, assign the open fid to the file */
 342        err = finish_open(file, dentry, generic_file_open);
 343        if (err)
 344                goto err_clunk_old_fid;
 345        file->private_data = ofid;
 346        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
 347                fscache_use_cookie(v9fs_inode_cookie(v9inode),
 348                                   file->f_mode & FMODE_WRITE);
 349        v9fs_open_fid_add(inode, ofid);
 350        file->f_mode |= FMODE_CREATED;
 351out:
 352        v9fs_put_acl(dacl, pacl);
 353        dput(res);
 354        return err;
 355
 356error:
 357        if (fid)
 358                p9_client_clunk(fid);
 359err_clunk_old_fid:
 360        if (ofid)
 361                p9_client_clunk(ofid);
 362        goto out;
 363}
 364
 365/**
 366 * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory
 367 * @mnt_userns: The user namespace of the mount
 368 * @dir:  inode that is being unlinked
 369 * @dentry: dentry that is being unlinked
 370 * @omode: mode for new directory
 371 *
 372 */
 373
 374static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 375                               struct inode *dir, struct dentry *dentry,
 376                               umode_t omode)
 377{
 378        int err;
 379        struct v9fs_session_info *v9ses;
 380        struct p9_fid *fid = NULL, *dfid = NULL;
 381        kgid_t gid;
 382        const unsigned char *name;
 383        umode_t mode;
 384        struct inode *inode;
 385        struct p9_qid qid;
 386        struct posix_acl *dacl = NULL, *pacl = NULL;
 387
 388        p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
 389        err = 0;
 390        v9ses = v9fs_inode2v9ses(dir);
 391
 392        omode |= S_IFDIR;
 393        if (dir->i_mode & S_ISGID)
 394                omode |= S_ISGID;
 395
 396        dfid = v9fs_parent_fid(dentry);
 397        if (IS_ERR(dfid)) {
 398                err = PTR_ERR(dfid);
 399                p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
 400                dfid = NULL;
 401                goto error;
 402        }
 403
 404        gid = v9fs_get_fsgid_for_create(dir);
 405        mode = omode;
 406        /* Update mode based on ACL value */
 407        err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
 408        if (err) {
 409                p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mkdir %d\n",
 410                         err);
 411                goto error;
 412        }
 413        name = dentry->d_name.name;
 414        err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
 415        if (err < 0)
 416                goto error;
 417        fid = p9_client_walk(dfid, 1, &name, 1);
 418        if (IS_ERR(fid)) {
 419                err = PTR_ERR(fid);
 420                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
 421                         err);
 422                fid = NULL;
 423                goto error;
 424        }
 425
 426        /* instantiate inode and assign the unopened fid to the dentry */
 427        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 428                inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 429                if (IS_ERR(inode)) {
 430                        err = PTR_ERR(inode);
 431                        p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
 432                                 err);
 433                        goto error;
 434                }
 435                v9fs_fid_add(dentry, fid);
 436                v9fs_set_create_acl(inode, fid, dacl, pacl);
 437                d_instantiate(dentry, inode);
 438                fid = NULL;
 439                err = 0;
 440        } else {
 441                /*
 442                 * Not in cached mode. No need to populate
 443                 * inode with stat. We need to get an inode
 444                 * so that we can set the acl with dentry
 445                 */
 446                inode = v9fs_get_inode(dir->i_sb, mode, 0);
 447                if (IS_ERR(inode)) {
 448                        err = PTR_ERR(inode);
 449                        goto error;
 450                }
 451                v9fs_set_create_acl(inode, fid, dacl, pacl);
 452                d_instantiate(dentry, inode);
 453        }
 454        inc_nlink(dir);
 455        v9fs_invalidate_inode_attr(dir);
 456error:
 457        if (fid)
 458                p9_client_clunk(fid);
 459        v9fs_put_acl(dacl, pacl);
 460        p9_client_clunk(dfid);
 461        return err;
 462}
 463
 464static int
 465v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
 466                      const struct path *path, struct kstat *stat,
 467                      u32 request_mask, unsigned int flags)
 468{
 469        struct dentry *dentry = path->dentry;
 470        struct v9fs_session_info *v9ses;
 471        struct p9_fid *fid;
 472        struct p9_stat_dotl *st;
 473
 474        p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
 475        v9ses = v9fs_dentry2v9ses(dentry);
 476        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 477                generic_fillattr(&init_user_ns, d_inode(dentry), stat);
 478                return 0;
 479        }
 480        fid = v9fs_fid_lookup(dentry);
 481        if (IS_ERR(fid))
 482                return PTR_ERR(fid);
 483
 484        /* Ask for all the fields in stat structure. Server will return
 485         * whatever it supports
 486         */
 487
 488        st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
 489        p9_client_clunk(fid);
 490        if (IS_ERR(st))
 491                return PTR_ERR(st);
 492
 493        v9fs_stat2inode_dotl(st, d_inode(dentry), 0);
 494        generic_fillattr(&init_user_ns, d_inode(dentry), stat);
 495        /* Change block size to what the server returned */
 496        stat->blksize = st->st_blksize;
 497
 498        kfree(st);
 499        return 0;
 500}
 501
 502/*
 503 * Attribute flags.
 504 */
 505#define P9_ATTR_MODE            (1 << 0)
 506#define P9_ATTR_UID             (1 << 1)
 507#define P9_ATTR_GID             (1 << 2)
 508#define P9_ATTR_SIZE            (1 << 3)
 509#define P9_ATTR_ATIME           (1 << 4)
 510#define P9_ATTR_MTIME           (1 << 5)
 511#define P9_ATTR_CTIME           (1 << 6)
 512#define P9_ATTR_ATIME_SET       (1 << 7)
 513#define P9_ATTR_MTIME_SET       (1 << 8)
 514
 515struct dotl_iattr_map {
 516        int iattr_valid;
 517        int p9_iattr_valid;
 518};
 519
 520static int v9fs_mapped_iattr_valid(int iattr_valid)
 521{
 522        int i;
 523        int p9_iattr_valid = 0;
 524        struct dotl_iattr_map dotl_iattr_map[] = {
 525                { ATTR_MODE,            P9_ATTR_MODE },
 526                { ATTR_UID,             P9_ATTR_UID },
 527                { ATTR_GID,             P9_ATTR_GID },
 528                { ATTR_SIZE,            P9_ATTR_SIZE },
 529                { ATTR_ATIME,           P9_ATTR_ATIME },
 530                { ATTR_MTIME,           P9_ATTR_MTIME },
 531                { ATTR_CTIME,           P9_ATTR_CTIME },
 532                { ATTR_ATIME_SET,       P9_ATTR_ATIME_SET },
 533                { ATTR_MTIME_SET,       P9_ATTR_MTIME_SET },
 534        };
 535        for (i = 0; i < ARRAY_SIZE(dotl_iattr_map); i++) {
 536                if (iattr_valid & dotl_iattr_map[i].iattr_valid)
 537                        p9_iattr_valid |= dotl_iattr_map[i].p9_iattr_valid;
 538        }
 539        return p9_iattr_valid;
 540}
 541
 542/**
 543 * v9fs_vfs_setattr_dotl - set file metadata
 544 * @mnt_userns: The user namespace of the mount
 545 * @dentry: file whose metadata to set
 546 * @iattr: metadata assignment structure
 547 *
 548 */
 549
 550int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 551                          struct dentry *dentry, struct iattr *iattr)
 552{
 553        int retval, use_dentry = 0;
 554        struct p9_fid *fid = NULL;
 555        struct p9_iattr_dotl p9attr = {
 556                .uid = INVALID_UID,
 557                .gid = INVALID_GID,
 558        };
 559        struct inode *inode = d_inode(dentry);
 560
 561        p9_debug(P9_DEBUG_VFS, "\n");
 562
 563        retval = setattr_prepare(&init_user_ns, dentry, iattr);
 564        if (retval)
 565                return retval;
 566
 567        p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid);
 568        if (iattr->ia_valid & ATTR_MODE)
 569                p9attr.mode = iattr->ia_mode;
 570        if (iattr->ia_valid & ATTR_UID)
 571                p9attr.uid = iattr->ia_uid;
 572        if (iattr->ia_valid & ATTR_GID)
 573                p9attr.gid = iattr->ia_gid;
 574        if (iattr->ia_valid & ATTR_SIZE)
 575                p9attr.size = iattr->ia_size;
 576        if (iattr->ia_valid & ATTR_ATIME_SET) {
 577                p9attr.atime_sec = iattr->ia_atime.tv_sec;
 578                p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
 579        }
 580        if (iattr->ia_valid & ATTR_MTIME_SET) {
 581                p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
 582                p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
 583        }
 584
 585        if (iattr->ia_valid & ATTR_FILE) {
 586                fid = iattr->ia_file->private_data;
 587                WARN_ON(!fid);
 588        }
 589        if (!fid) {
 590                fid = v9fs_fid_lookup(dentry);
 591                use_dentry = 1;
 592        }
 593        if (IS_ERR(fid))
 594                return PTR_ERR(fid);
 595
 596        /* Write all dirty data */
 597        if (S_ISREG(inode->i_mode))
 598                filemap_write_and_wait(inode->i_mapping);
 599
 600        retval = p9_client_setattr(fid, &p9attr);
 601        if (retval < 0) {
 602                if (use_dentry)
 603                        p9_client_clunk(fid);
 604                return retval;
 605        }
 606
 607        if ((iattr->ia_valid & ATTR_SIZE) &&
 608            iattr->ia_size != i_size_read(inode))
 609                truncate_setsize(inode, iattr->ia_size);
 610
 611        v9fs_invalidate_inode_attr(inode);
 612        setattr_copy(&init_user_ns, inode, iattr);
 613        mark_inode_dirty(inode);
 614        if (iattr->ia_valid & ATTR_MODE) {
 615                /* We also want to update ACL when we update mode bits */
 616                retval = v9fs_acl_chmod(inode, fid);
 617                if (retval < 0) {
 618                        if (use_dentry)
 619                                p9_client_clunk(fid);
 620                        return retval;
 621                }
 622        }
 623        if (use_dentry)
 624                p9_client_clunk(fid);
 625
 626        return 0;
 627}
 628
 629/**
 630 * v9fs_stat2inode_dotl - populate an inode structure with stat info
 631 * @stat: stat structure
 632 * @inode: inode to populate
 633 * @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
 634 *
 635 */
 636
 637void
 638v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
 639                      unsigned int flags)
 640{
 641        umode_t mode;
 642        struct v9fs_inode *v9inode = V9FS_I(inode);
 643
 644        if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
 645                inode->i_atime.tv_sec = stat->st_atime_sec;
 646                inode->i_atime.tv_nsec = stat->st_atime_nsec;
 647                inode->i_mtime.tv_sec = stat->st_mtime_sec;
 648                inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
 649                inode->i_ctime.tv_sec = stat->st_ctime_sec;
 650                inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
 651                inode->i_uid = stat->st_uid;
 652                inode->i_gid = stat->st_gid;
 653                set_nlink(inode, stat->st_nlink);
 654
 655                mode = stat->st_mode & S_IALLUGO;
 656                mode |= inode->i_mode & ~S_IALLUGO;
 657                inode->i_mode = mode;
 658
 659                if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
 660                        v9fs_i_size_write(inode, stat->st_size);
 661                inode->i_blocks = stat->st_blocks;
 662        } else {
 663                if (stat->st_result_mask & P9_STATS_ATIME) {
 664                        inode->i_atime.tv_sec = stat->st_atime_sec;
 665                        inode->i_atime.tv_nsec = stat->st_atime_nsec;
 666                }
 667                if (stat->st_result_mask & P9_STATS_MTIME) {
 668                        inode->i_mtime.tv_sec = stat->st_mtime_sec;
 669                        inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
 670                }
 671                if (stat->st_result_mask & P9_STATS_CTIME) {
 672                        inode->i_ctime.tv_sec = stat->st_ctime_sec;
 673                        inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
 674                }
 675                if (stat->st_result_mask & P9_STATS_UID)
 676                        inode->i_uid = stat->st_uid;
 677                if (stat->st_result_mask & P9_STATS_GID)
 678                        inode->i_gid = stat->st_gid;
 679                if (stat->st_result_mask & P9_STATS_NLINK)
 680                        set_nlink(inode, stat->st_nlink);
 681                if (stat->st_result_mask & P9_STATS_MODE) {
 682                        mode = stat->st_mode & S_IALLUGO;
 683                        mode |= inode->i_mode & ~S_IALLUGO;
 684                        inode->i_mode = mode;
 685                }
 686                if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) &&
 687                    stat->st_result_mask & P9_STATS_SIZE)
 688                        v9fs_i_size_write(inode, stat->st_size);
 689                if (stat->st_result_mask & P9_STATS_BLOCKS)
 690                        inode->i_blocks = stat->st_blocks;
 691        }
 692        if (stat->st_result_mask & P9_STATS_GEN)
 693                inode->i_generation = stat->st_gen;
 694
 695        /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
 696         * because the inode structure does not have fields for them.
 697         */
 698        v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
 699}
 700
 701static int
 702v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 703                      struct dentry *dentry, const char *symname)
 704{
 705        int err;
 706        kgid_t gid;
 707        const unsigned char *name;
 708        struct p9_qid qid;
 709        struct inode *inode;
 710        struct p9_fid *dfid;
 711        struct p9_fid *fid = NULL;
 712        struct v9fs_session_info *v9ses;
 713
 714        name = dentry->d_name.name;
 715        p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname);
 716        v9ses = v9fs_inode2v9ses(dir);
 717
 718        dfid = v9fs_parent_fid(dentry);
 719        if (IS_ERR(dfid)) {
 720                err = PTR_ERR(dfid);
 721                p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
 722                return err;
 723        }
 724
 725        gid = v9fs_get_fsgid_for_create(dir);
 726
 727        /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */
 728        err = p9_client_symlink(dfid, name, symname, gid, &qid);
 729
 730        if (err < 0) {
 731                p9_debug(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err);
 732                goto error;
 733        }
 734
 735        v9fs_invalidate_inode_attr(dir);
 736        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 737                /* Now walk from the parent so we can get an unopened fid. */
 738                fid = p9_client_walk(dfid, 1, &name, 1);
 739                if (IS_ERR(fid)) {
 740                        err = PTR_ERR(fid);
 741                        p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
 742                                 err);
 743                        fid = NULL;
 744                        goto error;
 745                }
 746
 747                /* instantiate inode and assign the unopened fid to dentry */
 748                inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 749                if (IS_ERR(inode)) {
 750                        err = PTR_ERR(inode);
 751                        p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
 752                                 err);
 753                        goto error;
 754                }
 755                v9fs_fid_add(dentry, fid);
 756                d_instantiate(dentry, inode);
 757                fid = NULL;
 758                err = 0;
 759        } else {
 760                /* Not in cached mode. No need to populate inode with stat */
 761                inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);
 762                if (IS_ERR(inode)) {
 763                        err = PTR_ERR(inode);
 764                        goto error;
 765                }
 766                d_instantiate(dentry, inode);
 767        }
 768
 769error:
 770        if (fid)
 771                p9_client_clunk(fid);
 772
 773        p9_client_clunk(dfid);
 774        return err;
 775}
 776
 777/**
 778 * v9fs_vfs_link_dotl - create a hardlink for dotl
 779 * @old_dentry: dentry for file to link to
 780 * @dir: inode destination for new link
 781 * @dentry: dentry for link
 782 *
 783 */
 784
 785static int
 786v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 787                struct dentry *dentry)
 788{
 789        int err;
 790        struct p9_fid *dfid, *oldfid;
 791        struct v9fs_session_info *v9ses;
 792
 793        p9_debug(P9_DEBUG_VFS, "dir ino: %lu, old_name: %pd, new_name: %pd\n",
 794                 dir->i_ino, old_dentry, dentry);
 795
 796        v9ses = v9fs_inode2v9ses(dir);
 797        dfid = v9fs_parent_fid(dentry);
 798        if (IS_ERR(dfid))
 799                return PTR_ERR(dfid);
 800
 801        oldfid = v9fs_fid_lookup(old_dentry);
 802        if (IS_ERR(oldfid)) {
 803                p9_client_clunk(dfid);
 804                return PTR_ERR(oldfid);
 805        }
 806
 807        err = p9_client_link(dfid, oldfid, dentry->d_name.name);
 808
 809        p9_client_clunk(dfid);
 810        p9_client_clunk(oldfid);
 811        if (err < 0) {
 812                p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
 813                return err;
 814        }
 815
 816        v9fs_invalidate_inode_attr(dir);
 817        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 818                /* Get the latest stat info from server. */
 819                struct p9_fid *fid;
 820
 821                fid = v9fs_fid_lookup(old_dentry);
 822                if (IS_ERR(fid))
 823                        return PTR_ERR(fid);
 824
 825                v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
 826                p9_client_clunk(fid);
 827        }
 828        ihold(d_inode(old_dentry));
 829        d_instantiate(dentry, d_inode(old_dentry));
 830
 831        return err;
 832}
 833
 834/**
 835 * v9fs_vfs_mknod_dotl - create a special file
 836 * @mnt_userns: The user namespace of the mount
 837 * @dir: inode destination for new link
 838 * @dentry: dentry for file
 839 * @omode: mode for creation
 840 * @rdev: device associated with special file
 841 *
 842 */
 843static int
 844v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 845                    struct dentry *dentry, umode_t omode, dev_t rdev)
 846{
 847        int err;
 848        kgid_t gid;
 849        const unsigned char *name;
 850        umode_t mode;
 851        struct v9fs_session_info *v9ses;
 852        struct p9_fid *fid = NULL, *dfid = NULL;
 853        struct inode *inode;
 854        struct p9_qid qid;
 855        struct posix_acl *dacl = NULL, *pacl = NULL;
 856
 857        p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n",
 858                 dir->i_ino, dentry, omode,
 859                 MAJOR(rdev), MINOR(rdev));
 860
 861        v9ses = v9fs_inode2v9ses(dir);
 862        dfid = v9fs_parent_fid(dentry);
 863        if (IS_ERR(dfid)) {
 864                err = PTR_ERR(dfid);
 865                p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
 866                dfid = NULL;
 867                goto error;
 868        }
 869
 870        gid = v9fs_get_fsgid_for_create(dir);
 871        mode = omode;
 872        /* Update mode based on ACL value */
 873        err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
 874        if (err) {
 875                p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mknod %d\n",
 876                         err);
 877                goto error;
 878        }
 879        name = dentry->d_name.name;
 880
 881        err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
 882        if (err < 0)
 883                goto error;
 884
 885        v9fs_invalidate_inode_attr(dir);
 886        fid = p9_client_walk(dfid, 1, &name, 1);
 887        if (IS_ERR(fid)) {
 888                err = PTR_ERR(fid);
 889                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
 890                         err);
 891                fid = NULL;
 892                goto error;
 893        }
 894
 895        /* instantiate inode and assign the unopened fid to the dentry */
 896        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 897                inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 898                if (IS_ERR(inode)) {
 899                        err = PTR_ERR(inode);
 900                        p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
 901                                 err);
 902                        goto error;
 903                }
 904                v9fs_set_create_acl(inode, fid, dacl, pacl);
 905                v9fs_fid_add(dentry, fid);
 906                d_instantiate(dentry, inode);
 907                fid = NULL;
 908                err = 0;
 909        } else {
 910                /*
 911                 * Not in cached mode. No need to populate inode with stat.
 912                 * socket syscall returns a fd, so we need instantiate
 913                 */
 914                inode = v9fs_get_inode(dir->i_sb, mode, rdev);
 915                if (IS_ERR(inode)) {
 916                        err = PTR_ERR(inode);
 917                        goto error;
 918                }
 919                v9fs_set_create_acl(inode, fid, dacl, pacl);
 920                d_instantiate(dentry, inode);
 921        }
 922error:
 923        if (fid)
 924                p9_client_clunk(fid);
 925        v9fs_put_acl(dacl, pacl);
 926        p9_client_clunk(dfid);
 927
 928        return err;
 929}
 930
 931/**
 932 * v9fs_vfs_get_link_dotl - follow a symlink path
 933 * @dentry: dentry for symlink
 934 * @inode: inode for symlink
 935 * @done: destructor for return value
 936 */
 937
 938static const char *
 939v9fs_vfs_get_link_dotl(struct dentry *dentry,
 940                       struct inode *inode,
 941                       struct delayed_call *done)
 942{
 943        struct p9_fid *fid;
 944        char *target;
 945        int retval;
 946
 947        if (!dentry)
 948                return ERR_PTR(-ECHILD);
 949
 950        p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
 951
 952        fid = v9fs_fid_lookup(dentry);
 953        if (IS_ERR(fid))
 954                return ERR_CAST(fid);
 955        retval = p9_client_readlink(fid, &target);
 956        p9_client_clunk(fid);
 957        if (retval)
 958                return ERR_PTR(retval);
 959        set_delayed_call(done, kfree_link, target);
 960        return target;
 961}
 962
 963int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
 964{
 965        struct p9_stat_dotl *st;
 966        struct v9fs_session_info *v9ses;
 967        unsigned int flags;
 968
 969        v9ses = v9fs_inode2v9ses(inode);
 970        st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
 971        if (IS_ERR(st))
 972                return PTR_ERR(st);
 973        /*
 974         * Don't update inode if the file type is different
 975         */
 976        if (inode_wrong_type(inode, st->st_mode))
 977                goto out;
 978
 979        /*
 980         * We don't want to refresh inode->i_size,
 981         * because we may have cached data
 982         */
 983        flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
 984                V9FS_STAT2INODE_KEEP_ISIZE : 0;
 985        v9fs_stat2inode_dotl(st, inode, flags);
 986out:
 987        kfree(st);
 988        return 0;
 989}
 990
 991const struct inode_operations v9fs_dir_inode_operations_dotl = {
 992        .create = v9fs_vfs_create_dotl,
 993        .atomic_open = v9fs_vfs_atomic_open_dotl,
 994        .lookup = v9fs_vfs_lookup,
 995        .link = v9fs_vfs_link_dotl,
 996        .symlink = v9fs_vfs_symlink_dotl,
 997        .unlink = v9fs_vfs_unlink,
 998        .mkdir = v9fs_vfs_mkdir_dotl,
 999        .rmdir = v9fs_vfs_rmdir,
1000        .mknod = v9fs_vfs_mknod_dotl,
1001        .rename = v9fs_vfs_rename,
1002        .getattr = v9fs_vfs_getattr_dotl,
1003        .setattr = v9fs_vfs_setattr_dotl,
1004        .listxattr = v9fs_listxattr,
1005        .get_acl = v9fs_iop_get_acl,
1006};
1007
1008const struct inode_operations v9fs_file_inode_operations_dotl = {
1009        .getattr = v9fs_vfs_getattr_dotl,
1010        .setattr = v9fs_vfs_setattr_dotl,
1011        .listxattr = v9fs_listxattr,
1012        .get_acl = v9fs_iop_get_acl,
1013};
1014
1015const struct inode_operations v9fs_symlink_inode_operations_dotl = {
1016        .get_link = v9fs_vfs_get_link_dotl,
1017        .getattr = v9fs_vfs_getattr_dotl,
1018        .setattr = v9fs_vfs_setattr_dotl,
1019        .listxattr = v9fs_listxattr,
1020};
1021