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