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