Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This file contains vfs inode ops for the 9P2000.L protocol.
0004  *
0005  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
0006  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/errno.h>
0011 #include <linux/fs.h>
0012 #include <linux/file.h>
0013 #include <linux/pagemap.h>
0014 #include <linux/stat.h>
0015 #include <linux/string.h>
0016 #include <linux/inet.h>
0017 #include <linux/namei.h>
0018 #include <linux/idr.h>
0019 #include <linux/sched.h>
0020 #include <linux/slab.h>
0021 #include <linux/xattr.h>
0022 #include <linux/posix_acl.h>
0023 #include <net/9p/9p.h>
0024 #include <net/9p/client.h>
0025 
0026 #include "v9fs.h"
0027 #include "v9fs_vfs.h"
0028 #include "fid.h"
0029 #include "cache.h"
0030 #include "xattr.h"
0031 #include "acl.h"
0032 
0033 static int
0034 v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
0035             struct dentry *dentry, umode_t omode, dev_t rdev);
0036 
0037 /**
0038  * v9fs_get_fsgid_for_create - Helper function to get the gid for a new object
0039  * @dir_inode: The directory inode
0040  *
0041  * Helper function to get the gid for creating a
0042  * new file system object. This checks the S_ISGID to determine the owning
0043  * group of the new file system object.
0044  */
0045 
0046 static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
0047 {
0048     BUG_ON(dir_inode == NULL);
0049 
0050     if (dir_inode->i_mode & S_ISGID) {
0051         /* set_gid bit is set.*/
0052         return dir_inode->i_gid;
0053     }
0054     return current_fsgid();
0055 }
0056 
0057 static int v9fs_test_inode_dotl(struct inode *inode, void *data)
0058 {
0059     struct v9fs_inode *v9inode = V9FS_I(inode);
0060     struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
0061 
0062     /* don't match inode of different type */
0063     if (inode_wrong_type(inode, st->st_mode))
0064         return 0;
0065 
0066     if (inode->i_generation != st->st_gen)
0067         return 0;
0068 
0069     /* compare qid details */
0070     if (memcmp(&v9inode->qid.version,
0071            &st->qid.version, sizeof(v9inode->qid.version)))
0072         return 0;
0073 
0074     if (v9inode->qid.type != st->qid.type)
0075         return 0;
0076 
0077     if (v9inode->qid.path != st->qid.path)
0078         return 0;
0079     return 1;
0080 }
0081 
0082 /* Always get a new inode */
0083 static int v9fs_test_new_inode_dotl(struct inode *inode, void *data)
0084 {
0085     return 0;
0086 }
0087 
0088 static int v9fs_set_inode_dotl(struct inode *inode,  void *data)
0089 {
0090     struct v9fs_inode *v9inode = V9FS_I(inode);
0091     struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
0092 
0093     memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
0094     inode->i_generation = st->st_gen;
0095     return 0;
0096 }
0097 
0098 static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
0099                     struct p9_qid *qid,
0100                     struct p9_fid *fid,
0101                     struct p9_stat_dotl *st,
0102                     int new)
0103 {
0104     int retval;
0105     unsigned long i_ino;
0106     struct inode *inode;
0107     struct v9fs_session_info *v9ses = sb->s_fs_info;
0108     int (*test)(struct inode *inode, void *data);
0109 
0110     if (new)
0111         test = v9fs_test_new_inode_dotl;
0112     else
0113         test = v9fs_test_inode_dotl;
0114 
0115     i_ino = v9fs_qid2ino(qid);
0116     inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
0117     if (!inode)
0118         return ERR_PTR(-ENOMEM);
0119     if (!(inode->i_state & I_NEW))
0120         return inode;
0121     /*
0122      * initialize the inode with the stat info
0123      * FIXME!! we may need support for stale inodes
0124      * later.
0125      */
0126     inode->i_ino = i_ino;
0127     retval = v9fs_init_inode(v9ses, inode,
0128                  st->st_mode, new_decode_dev(st->st_rdev));
0129     if (retval)
0130         goto error;
0131 
0132     v9fs_stat2inode_dotl(st, inode, 0);
0133     v9fs_cache_inode_get_cookie(inode);
0134     retval = v9fs_get_acl(inode, fid);
0135     if (retval)
0136         goto error;
0137 
0138     unlock_new_inode(inode);
0139     return inode;
0140 error:
0141     iget_failed(inode);
0142     return ERR_PTR(retval);
0143 
0144 }
0145 
0146 struct inode *
0147 v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
0148              struct super_block *sb, int new)
0149 {
0150     struct p9_stat_dotl *st;
0151     struct inode *inode = NULL;
0152 
0153     st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN);
0154     if (IS_ERR(st))
0155         return ERR_CAST(st);
0156 
0157     inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new);
0158     kfree(st);
0159     return inode;
0160 }
0161 
0162 struct dotl_openflag_map {
0163     int open_flag;
0164     int dotl_flag;
0165 };
0166 
0167 static int v9fs_mapped_dotl_flags(int flags)
0168 {
0169     int i;
0170     int rflags = 0;
0171     struct dotl_openflag_map dotl_oflag_map[] = {
0172         { O_CREAT,  P9_DOTL_CREATE },
0173         { O_EXCL,   P9_DOTL_EXCL },
0174         { O_NOCTTY, P9_DOTL_NOCTTY },
0175         { O_APPEND, P9_DOTL_APPEND },
0176         { O_NONBLOCK,   P9_DOTL_NONBLOCK },
0177         { O_DSYNC,  P9_DOTL_DSYNC },
0178         { FASYNC,   P9_DOTL_FASYNC },
0179         { O_DIRECT, P9_DOTL_DIRECT },
0180         { O_LARGEFILE,  P9_DOTL_LARGEFILE },
0181         { O_DIRECTORY,  P9_DOTL_DIRECTORY },
0182         { O_NOFOLLOW,   P9_DOTL_NOFOLLOW },
0183         { O_NOATIME,    P9_DOTL_NOATIME },
0184         { O_CLOEXEC,    P9_DOTL_CLOEXEC },
0185         { O_SYNC,   P9_DOTL_SYNC},
0186     };
0187     for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
0188         if (flags & dotl_oflag_map[i].open_flag)
0189             rflags |= dotl_oflag_map[i].dotl_flag;
0190     }
0191     return rflags;
0192 }
0193 
0194 /**
0195  * v9fs_open_to_dotl_flags- convert Linux specific open flags to
0196  * plan 9 open flag.
0197  * @flags: flags to convert
0198  */
0199 int v9fs_open_to_dotl_flags(int flags)
0200 {
0201     int rflags = 0;
0202 
0203     /*
0204      * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
0205      * and P9_DOTL_NOACCESS
0206      */
0207     rflags |= flags & O_ACCMODE;
0208     rflags |= v9fs_mapped_dotl_flags(flags);
0209 
0210     return rflags;
0211 }
0212 
0213 /**
0214  * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
0215  * @mnt_userns: The user namespace of the mount
0216  * @dir: directory inode that is being created
0217  * @dentry:  dentry that is being deleted
0218  * @omode: create permissions
0219  * @excl: True if the file must not yet exist
0220  *
0221  */
0222 static int
0223 v9fs_vfs_create_dotl(struct user_namespace *mnt_userns, struct inode *dir,
0224              struct dentry *dentry, umode_t omode, bool excl)
0225 {
0226     return v9fs_vfs_mknod_dotl(mnt_userns, dir, dentry, omode, 0);
0227 }
0228 
0229 static int
0230 v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
0231               struct file *file, unsigned int flags, umode_t omode)
0232 {
0233     int err = 0;
0234     kgid_t gid;
0235     umode_t mode;
0236     const unsigned char *name = NULL;
0237     struct p9_qid qid;
0238     struct inode *inode;
0239     struct p9_fid *fid = NULL;
0240     struct v9fs_inode *v9inode;
0241     struct p9_fid *dfid = NULL, *ofid = NULL, *inode_fid = NULL;
0242     struct v9fs_session_info *v9ses;
0243     struct posix_acl *pacl = NULL, *dacl = NULL;
0244     struct dentry *res = NULL;
0245 
0246     if (d_in_lookup(dentry)) {
0247         res = v9fs_vfs_lookup(dir, dentry, 0);
0248         if (IS_ERR(res))
0249             return PTR_ERR(res);
0250 
0251         if (res)
0252             dentry = res;
0253     }
0254 
0255     /* Only creates */
0256     if (!(flags & O_CREAT) || d_really_is_positive(dentry))
0257         return  finish_no_open(file, res);
0258 
0259     v9ses = v9fs_inode2v9ses(dir);
0260 
0261     name = dentry->d_name.name;
0262     p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%x\n",
0263          name, flags, omode);
0264 
0265     dfid = v9fs_parent_fid(dentry);
0266     if (IS_ERR(dfid)) {
0267         err = PTR_ERR(dfid);
0268         p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
0269         goto out;
0270     }
0271 
0272     /* clone a fid to use for creation */
0273     ofid = clone_fid(dfid);
0274     if (IS_ERR(ofid)) {
0275         err = PTR_ERR(ofid);
0276         p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
0277         goto out;
0278     }
0279 
0280     gid = v9fs_get_fsgid_for_create(dir);
0281 
0282     mode = omode;
0283     /* Update mode based on ACL value */
0284     err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
0285     if (err) {
0286         p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
0287              err);
0288         goto out;
0289     }
0290     err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
0291                     mode, gid, &qid);
0292     if (err < 0) {
0293         p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
0294              err);
0295         goto out;
0296     }
0297     v9fs_invalidate_inode_attr(dir);
0298 
0299     /* instantiate inode and assign the unopened fid to the dentry */
0300     fid = p9_client_walk(dfid, 1, &name, 1);
0301     if (IS_ERR(fid)) {
0302         err = PTR_ERR(fid);
0303         p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
0304         goto out;
0305     }
0306     inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
0307     if (IS_ERR(inode)) {
0308         err = PTR_ERR(inode);
0309         p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
0310         goto out;
0311     }
0312     /* Now set the ACL based on the default value */
0313     v9fs_set_create_acl(inode, fid, dacl, pacl);
0314 
0315     v9fs_fid_add(dentry, &fid);
0316     d_instantiate(dentry, inode);
0317 
0318     v9inode = V9FS_I(inode);
0319     mutex_lock(&v9inode->v_mutex);
0320     if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
0321         !v9inode->writeback_fid &&
0322         ((flags & O_ACCMODE) != O_RDONLY)) {
0323         /*
0324          * clone a fid and add it to writeback_fid
0325          * we do it during open time instead of
0326          * page dirty time via write_begin/page_mkwrite
0327          * because we want write after unlink usecase
0328          * to work.
0329          */
0330         inode_fid = v9fs_writeback_fid(dentry);
0331         if (IS_ERR(inode_fid)) {
0332             err = PTR_ERR(inode_fid);
0333             mutex_unlock(&v9inode->v_mutex);
0334             goto out;
0335         }
0336         v9inode->writeback_fid = (void *) inode_fid;
0337     }
0338     mutex_unlock(&v9inode->v_mutex);
0339     /* Since we are opening a file, assign the open fid to the file */
0340     err = finish_open(file, dentry, generic_file_open);
0341     if (err)
0342         goto out;
0343     file->private_data = ofid;
0344     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
0345         fscache_use_cookie(v9fs_inode_cookie(v9inode),
0346                    file->f_mode & FMODE_WRITE);
0347     v9fs_open_fid_add(inode, &ofid);
0348     file->f_mode |= FMODE_CREATED;
0349 out:
0350     p9_fid_put(dfid);
0351     p9_fid_put(ofid);
0352     p9_fid_put(fid);
0353     v9fs_put_acl(dacl, pacl);
0354     dput(res);
0355     return err;
0356 }
0357 
0358 /**
0359  * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory
0360  * @mnt_userns: The user namespace of the mount
0361  * @dir:  inode that is being unlinked
0362  * @dentry: dentry that is being unlinked
0363  * @omode: mode for new directory
0364  *
0365  */
0366 
0367 static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
0368                    struct inode *dir, struct dentry *dentry,
0369                    umode_t omode)
0370 {
0371     int err;
0372     struct v9fs_session_info *v9ses;
0373     struct p9_fid *fid = NULL, *dfid = NULL;
0374     kgid_t gid;
0375     const unsigned char *name;
0376     umode_t mode;
0377     struct inode *inode;
0378     struct p9_qid qid;
0379     struct posix_acl *dacl = NULL, *pacl = NULL;
0380 
0381     p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
0382     err = 0;
0383     v9ses = v9fs_inode2v9ses(dir);
0384 
0385     omode |= S_IFDIR;
0386     if (dir->i_mode & S_ISGID)
0387         omode |= S_ISGID;
0388 
0389     dfid = v9fs_parent_fid(dentry);
0390     if (IS_ERR(dfid)) {
0391         err = PTR_ERR(dfid);
0392         p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
0393         goto error;
0394     }
0395 
0396     gid = v9fs_get_fsgid_for_create(dir);
0397     mode = omode;
0398     /* Update mode based on ACL value */
0399     err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
0400     if (err) {
0401         p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mkdir %d\n",
0402              err);
0403         goto error;
0404     }
0405     name = dentry->d_name.name;
0406     err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
0407     if (err < 0)
0408         goto error;
0409     fid = p9_client_walk(dfid, 1, &name, 1);
0410     if (IS_ERR(fid)) {
0411         err = PTR_ERR(fid);
0412         p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
0413              err);
0414         goto error;
0415     }
0416 
0417     /* instantiate inode and assign the unopened fid to the dentry */
0418     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
0419         inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
0420         if (IS_ERR(inode)) {
0421             err = PTR_ERR(inode);
0422             p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
0423                  err);
0424             goto error;
0425         }
0426         v9fs_fid_add(dentry, &fid);
0427         v9fs_set_create_acl(inode, fid, dacl, pacl);
0428         d_instantiate(dentry, inode);
0429         err = 0;
0430     } else {
0431         /*
0432          * Not in cached mode. No need to populate
0433          * inode with stat. We need to get an inode
0434          * so that we can set the acl with dentry
0435          */
0436         inode = v9fs_get_inode(dir->i_sb, mode, 0);
0437         if (IS_ERR(inode)) {
0438             err = PTR_ERR(inode);
0439             goto error;
0440         }
0441         v9fs_set_create_acl(inode, fid, dacl, pacl);
0442         d_instantiate(dentry, inode);
0443     }
0444     inc_nlink(dir);
0445     v9fs_invalidate_inode_attr(dir);
0446 error:
0447     p9_fid_put(fid);
0448     v9fs_put_acl(dacl, pacl);
0449     p9_fid_put(dfid);
0450     return err;
0451 }
0452 
0453 static int
0454 v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
0455               const struct path *path, struct kstat *stat,
0456               u32 request_mask, unsigned int flags)
0457 {
0458     struct dentry *dentry = path->dentry;
0459     struct v9fs_session_info *v9ses;
0460     struct p9_fid *fid;
0461     struct p9_stat_dotl *st;
0462 
0463     p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
0464     v9ses = v9fs_dentry2v9ses(dentry);
0465     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
0466         generic_fillattr(&init_user_ns, d_inode(dentry), stat);
0467         return 0;
0468     }
0469     fid = v9fs_fid_lookup(dentry);
0470     if (IS_ERR(fid))
0471         return PTR_ERR(fid);
0472 
0473     /* Ask for all the fields in stat structure. Server will return
0474      * whatever it supports
0475      */
0476 
0477     st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
0478     p9_fid_put(fid);
0479     if (IS_ERR(st))
0480         return PTR_ERR(st);
0481 
0482     v9fs_stat2inode_dotl(st, d_inode(dentry), 0);
0483     generic_fillattr(&init_user_ns, d_inode(dentry), stat);
0484     /* Change block size to what the server returned */
0485     stat->blksize = st->st_blksize;
0486 
0487     kfree(st);
0488     return 0;
0489 }
0490 
0491 /*
0492  * Attribute flags.
0493  */
0494 #define P9_ATTR_MODE        (1 << 0)
0495 #define P9_ATTR_UID     (1 << 1)
0496 #define P9_ATTR_GID     (1 << 2)
0497 #define P9_ATTR_SIZE        (1 << 3)
0498 #define P9_ATTR_ATIME       (1 << 4)
0499 #define P9_ATTR_MTIME       (1 << 5)
0500 #define P9_ATTR_CTIME       (1 << 6)
0501 #define P9_ATTR_ATIME_SET   (1 << 7)
0502 #define P9_ATTR_MTIME_SET   (1 << 8)
0503 
0504 struct dotl_iattr_map {
0505     int iattr_valid;
0506     int p9_iattr_valid;
0507 };
0508 
0509 static int v9fs_mapped_iattr_valid(int iattr_valid)
0510 {
0511     int i;
0512     int p9_iattr_valid = 0;
0513     struct dotl_iattr_map dotl_iattr_map[] = {
0514         { ATTR_MODE,        P9_ATTR_MODE },
0515         { ATTR_UID,     P9_ATTR_UID },
0516         { ATTR_GID,     P9_ATTR_GID },
0517         { ATTR_SIZE,        P9_ATTR_SIZE },
0518         { ATTR_ATIME,       P9_ATTR_ATIME },
0519         { ATTR_MTIME,       P9_ATTR_MTIME },
0520         { ATTR_CTIME,       P9_ATTR_CTIME },
0521         { ATTR_ATIME_SET,   P9_ATTR_ATIME_SET },
0522         { ATTR_MTIME_SET,   P9_ATTR_MTIME_SET },
0523     };
0524     for (i = 0; i < ARRAY_SIZE(dotl_iattr_map); i++) {
0525         if (iattr_valid & dotl_iattr_map[i].iattr_valid)
0526             p9_iattr_valid |= dotl_iattr_map[i].p9_iattr_valid;
0527     }
0528     return p9_iattr_valid;
0529 }
0530 
0531 /**
0532  * v9fs_vfs_setattr_dotl - set file metadata
0533  * @mnt_userns: The user namespace of the mount
0534  * @dentry: file whose metadata to set
0535  * @iattr: metadata assignment structure
0536  *
0537  */
0538 
0539 int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
0540               struct dentry *dentry, struct iattr *iattr)
0541 {
0542     int retval, use_dentry = 0;
0543     struct p9_fid *fid = NULL;
0544     struct p9_iattr_dotl p9attr = {
0545         .uid = INVALID_UID,
0546         .gid = INVALID_GID,
0547     };
0548     struct inode *inode = d_inode(dentry);
0549 
0550     p9_debug(P9_DEBUG_VFS, "\n");
0551 
0552     retval = setattr_prepare(&init_user_ns, dentry, iattr);
0553     if (retval)
0554         return retval;
0555 
0556     p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid);
0557     if (iattr->ia_valid & ATTR_MODE)
0558         p9attr.mode = iattr->ia_mode;
0559     if (iattr->ia_valid & ATTR_UID)
0560         p9attr.uid = iattr->ia_uid;
0561     if (iattr->ia_valid & ATTR_GID)
0562         p9attr.gid = iattr->ia_gid;
0563     if (iattr->ia_valid & ATTR_SIZE)
0564         p9attr.size = iattr->ia_size;
0565     if (iattr->ia_valid & ATTR_ATIME_SET) {
0566         p9attr.atime_sec = iattr->ia_atime.tv_sec;
0567         p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
0568     }
0569     if (iattr->ia_valid & ATTR_MTIME_SET) {
0570         p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
0571         p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
0572     }
0573 
0574     if (iattr->ia_valid & ATTR_FILE) {
0575         fid = iattr->ia_file->private_data;
0576         WARN_ON(!fid);
0577     }
0578     if (!fid) {
0579         fid = v9fs_fid_lookup(dentry);
0580         use_dentry = 1;
0581     }
0582     if (IS_ERR(fid))
0583         return PTR_ERR(fid);
0584 
0585     /* Write all dirty data */
0586     if (S_ISREG(inode->i_mode))
0587         filemap_write_and_wait(inode->i_mapping);
0588 
0589     retval = p9_client_setattr(fid, &p9attr);
0590     if (retval < 0) {
0591         if (use_dentry)
0592             p9_fid_put(fid);
0593         return retval;
0594     }
0595 
0596     if ((iattr->ia_valid & ATTR_SIZE) &&
0597         iattr->ia_size != i_size_read(inode))
0598         truncate_setsize(inode, iattr->ia_size);
0599 
0600     v9fs_invalidate_inode_attr(inode);
0601     setattr_copy(&init_user_ns, inode, iattr);
0602     mark_inode_dirty(inode);
0603     if (iattr->ia_valid & ATTR_MODE) {
0604         /* We also want to update ACL when we update mode bits */
0605         retval = v9fs_acl_chmod(inode, fid);
0606         if (retval < 0) {
0607             if (use_dentry)
0608                 p9_fid_put(fid);
0609             return retval;
0610         }
0611     }
0612     if (use_dentry)
0613         p9_fid_put(fid);
0614 
0615     return 0;
0616 }
0617 
0618 /**
0619  * v9fs_stat2inode_dotl - populate an inode structure with stat info
0620  * @stat: stat structure
0621  * @inode: inode to populate
0622  * @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
0623  *
0624  */
0625 
0626 void
0627 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
0628               unsigned int flags)
0629 {
0630     umode_t mode;
0631     struct v9fs_inode *v9inode = V9FS_I(inode);
0632 
0633     if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
0634         inode->i_atime.tv_sec = stat->st_atime_sec;
0635         inode->i_atime.tv_nsec = stat->st_atime_nsec;
0636         inode->i_mtime.tv_sec = stat->st_mtime_sec;
0637         inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
0638         inode->i_ctime.tv_sec = stat->st_ctime_sec;
0639         inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
0640         inode->i_uid = stat->st_uid;
0641         inode->i_gid = stat->st_gid;
0642         set_nlink(inode, stat->st_nlink);
0643 
0644         mode = stat->st_mode & S_IALLUGO;
0645         mode |= inode->i_mode & ~S_IALLUGO;
0646         inode->i_mode = mode;
0647 
0648         if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
0649             v9fs_i_size_write(inode, stat->st_size);
0650         inode->i_blocks = stat->st_blocks;
0651     } else {
0652         if (stat->st_result_mask & P9_STATS_ATIME) {
0653             inode->i_atime.tv_sec = stat->st_atime_sec;
0654             inode->i_atime.tv_nsec = stat->st_atime_nsec;
0655         }
0656         if (stat->st_result_mask & P9_STATS_MTIME) {
0657             inode->i_mtime.tv_sec = stat->st_mtime_sec;
0658             inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
0659         }
0660         if (stat->st_result_mask & P9_STATS_CTIME) {
0661             inode->i_ctime.tv_sec = stat->st_ctime_sec;
0662             inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
0663         }
0664         if (stat->st_result_mask & P9_STATS_UID)
0665             inode->i_uid = stat->st_uid;
0666         if (stat->st_result_mask & P9_STATS_GID)
0667             inode->i_gid = stat->st_gid;
0668         if (stat->st_result_mask & P9_STATS_NLINK)
0669             set_nlink(inode, stat->st_nlink);
0670         if (stat->st_result_mask & P9_STATS_MODE) {
0671             mode = stat->st_mode & S_IALLUGO;
0672             mode |= inode->i_mode & ~S_IALLUGO;
0673             inode->i_mode = mode;
0674         }
0675         if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) &&
0676             stat->st_result_mask & P9_STATS_SIZE)
0677             v9fs_i_size_write(inode, stat->st_size);
0678         if (stat->st_result_mask & P9_STATS_BLOCKS)
0679             inode->i_blocks = stat->st_blocks;
0680     }
0681     if (stat->st_result_mask & P9_STATS_GEN)
0682         inode->i_generation = stat->st_gen;
0683 
0684     /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
0685      * because the inode structure does not have fields for them.
0686      */
0687     v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
0688 }
0689 
0690 static int
0691 v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
0692               struct dentry *dentry, const char *symname)
0693 {
0694     int err;
0695     kgid_t gid;
0696     const unsigned char *name;
0697     struct p9_qid qid;
0698     struct inode *inode;
0699     struct p9_fid *dfid;
0700     struct p9_fid *fid = NULL;
0701     struct v9fs_session_info *v9ses;
0702 
0703     name = dentry->d_name.name;
0704     p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname);
0705     v9ses = v9fs_inode2v9ses(dir);
0706 
0707     dfid = v9fs_parent_fid(dentry);
0708     if (IS_ERR(dfid)) {
0709         err = PTR_ERR(dfid);
0710         p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
0711         return err;
0712     }
0713 
0714     gid = v9fs_get_fsgid_for_create(dir);
0715 
0716     /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */
0717     err = p9_client_symlink(dfid, name, symname, gid, &qid);
0718 
0719     if (err < 0) {
0720         p9_debug(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err);
0721         goto error;
0722     }
0723 
0724     v9fs_invalidate_inode_attr(dir);
0725     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
0726         /* Now walk from the parent so we can get an unopened fid. */
0727         fid = p9_client_walk(dfid, 1, &name, 1);
0728         if (IS_ERR(fid)) {
0729             err = PTR_ERR(fid);
0730             p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
0731                  err);
0732             goto error;
0733         }
0734 
0735         /* instantiate inode and assign the unopened fid to dentry */
0736         inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
0737         if (IS_ERR(inode)) {
0738             err = PTR_ERR(inode);
0739             p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
0740                  err);
0741             goto error;
0742         }
0743         v9fs_fid_add(dentry, &fid);
0744         d_instantiate(dentry, inode);
0745         err = 0;
0746     } else {
0747         /* Not in cached mode. No need to populate inode with stat */
0748         inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);
0749         if (IS_ERR(inode)) {
0750             err = PTR_ERR(inode);
0751             goto error;
0752         }
0753         d_instantiate(dentry, inode);
0754     }
0755 
0756 error:
0757     p9_fid_put(fid);
0758     p9_fid_put(dfid);
0759     return err;
0760 }
0761 
0762 /**
0763  * v9fs_vfs_link_dotl - create a hardlink for dotl
0764  * @old_dentry: dentry for file to link to
0765  * @dir: inode destination for new link
0766  * @dentry: dentry for link
0767  *
0768  */
0769 
0770 static int
0771 v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
0772         struct dentry *dentry)
0773 {
0774     int err;
0775     struct p9_fid *dfid, *oldfid;
0776     struct v9fs_session_info *v9ses;
0777 
0778     p9_debug(P9_DEBUG_VFS, "dir ino: %lu, old_name: %pd, new_name: %pd\n",
0779          dir->i_ino, old_dentry, dentry);
0780 
0781     v9ses = v9fs_inode2v9ses(dir);
0782     dfid = v9fs_parent_fid(dentry);
0783     if (IS_ERR(dfid))
0784         return PTR_ERR(dfid);
0785 
0786     oldfid = v9fs_fid_lookup(old_dentry);
0787     if (IS_ERR(oldfid)) {
0788         p9_fid_put(dfid);
0789         return PTR_ERR(oldfid);
0790     }
0791 
0792     err = p9_client_link(dfid, oldfid, dentry->d_name.name);
0793 
0794     p9_fid_put(dfid);
0795     p9_fid_put(oldfid);
0796     if (err < 0) {
0797         p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
0798         return err;
0799     }
0800 
0801     v9fs_invalidate_inode_attr(dir);
0802     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
0803         /* Get the latest stat info from server. */
0804         struct p9_fid *fid;
0805 
0806         fid = v9fs_fid_lookup(old_dentry);
0807         if (IS_ERR(fid))
0808             return PTR_ERR(fid);
0809 
0810         v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
0811         p9_fid_put(fid);
0812     }
0813     ihold(d_inode(old_dentry));
0814     d_instantiate(dentry, d_inode(old_dentry));
0815 
0816     return err;
0817 }
0818 
0819 /**
0820  * v9fs_vfs_mknod_dotl - create a special file
0821  * @mnt_userns: The user namespace of the mount
0822  * @dir: inode destination for new link
0823  * @dentry: dentry for file
0824  * @omode: mode for creation
0825  * @rdev: device associated with special file
0826  *
0827  */
0828 static int
0829 v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
0830             struct dentry *dentry, umode_t omode, dev_t rdev)
0831 {
0832     int err;
0833     kgid_t gid;
0834     const unsigned char *name;
0835     umode_t mode;
0836     struct v9fs_session_info *v9ses;
0837     struct p9_fid *fid = NULL, *dfid = NULL;
0838     struct inode *inode;
0839     struct p9_qid qid;
0840     struct posix_acl *dacl = NULL, *pacl = NULL;
0841 
0842     p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n",
0843          dir->i_ino, dentry, omode,
0844          MAJOR(rdev), MINOR(rdev));
0845 
0846     v9ses = v9fs_inode2v9ses(dir);
0847     dfid = v9fs_parent_fid(dentry);
0848     if (IS_ERR(dfid)) {
0849         err = PTR_ERR(dfid);
0850         p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
0851         goto error;
0852     }
0853 
0854     gid = v9fs_get_fsgid_for_create(dir);
0855     mode = omode;
0856     /* Update mode based on ACL value */
0857     err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
0858     if (err) {
0859         p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mknod %d\n",
0860              err);
0861         goto error;
0862     }
0863     name = dentry->d_name.name;
0864 
0865     err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
0866     if (err < 0)
0867         goto error;
0868 
0869     v9fs_invalidate_inode_attr(dir);
0870     fid = p9_client_walk(dfid, 1, &name, 1);
0871     if (IS_ERR(fid)) {
0872         err = PTR_ERR(fid);
0873         p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
0874              err);
0875         goto error;
0876     }
0877 
0878     /* instantiate inode and assign the unopened fid to the dentry */
0879     if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
0880         inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
0881         if (IS_ERR(inode)) {
0882             err = PTR_ERR(inode);
0883             p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
0884                  err);
0885             goto error;
0886         }
0887         v9fs_set_create_acl(inode, fid, dacl, pacl);
0888         v9fs_fid_add(dentry, &fid);
0889         d_instantiate(dentry, inode);
0890         err = 0;
0891     } else {
0892         /*
0893          * Not in cached mode. No need to populate inode with stat.
0894          * socket syscall returns a fd, so we need instantiate
0895          */
0896         inode = v9fs_get_inode(dir->i_sb, mode, rdev);
0897         if (IS_ERR(inode)) {
0898             err = PTR_ERR(inode);
0899             goto error;
0900         }
0901         v9fs_set_create_acl(inode, fid, dacl, pacl);
0902         d_instantiate(dentry, inode);
0903     }
0904 error:
0905     p9_fid_put(fid);
0906     v9fs_put_acl(dacl, pacl);
0907     p9_fid_put(dfid);
0908 
0909     return err;
0910 }
0911 
0912 /**
0913  * v9fs_vfs_get_link_dotl - follow a symlink path
0914  * @dentry: dentry for symlink
0915  * @inode: inode for symlink
0916  * @done: destructor for return value
0917  */
0918 
0919 static const char *
0920 v9fs_vfs_get_link_dotl(struct dentry *dentry,
0921                struct inode *inode,
0922                struct delayed_call *done)
0923 {
0924     struct p9_fid *fid;
0925     char *target;
0926     int retval;
0927 
0928     if (!dentry)
0929         return ERR_PTR(-ECHILD);
0930 
0931     p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
0932 
0933     fid = v9fs_fid_lookup(dentry);
0934     if (IS_ERR(fid))
0935         return ERR_CAST(fid);
0936     retval = p9_client_readlink(fid, &target);
0937     p9_fid_put(fid);
0938     if (retval)
0939         return ERR_PTR(retval);
0940     set_delayed_call(done, kfree_link, target);
0941     return target;
0942 }
0943 
0944 int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
0945 {
0946     struct p9_stat_dotl *st;
0947     struct v9fs_session_info *v9ses;
0948     unsigned int flags;
0949 
0950     v9ses = v9fs_inode2v9ses(inode);
0951     st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
0952     if (IS_ERR(st))
0953         return PTR_ERR(st);
0954     /*
0955      * Don't update inode if the file type is different
0956      */
0957     if (inode_wrong_type(inode, st->st_mode))
0958         goto out;
0959 
0960     /*
0961      * We don't want to refresh inode->i_size,
0962      * because we may have cached data
0963      */
0964     flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
0965         V9FS_STAT2INODE_KEEP_ISIZE : 0;
0966     v9fs_stat2inode_dotl(st, inode, flags);
0967 out:
0968     kfree(st);
0969     return 0;
0970 }
0971 
0972 const struct inode_operations v9fs_dir_inode_operations_dotl = {
0973     .create = v9fs_vfs_create_dotl,
0974     .atomic_open = v9fs_vfs_atomic_open_dotl,
0975     .lookup = v9fs_vfs_lookup,
0976     .link = v9fs_vfs_link_dotl,
0977     .symlink = v9fs_vfs_symlink_dotl,
0978     .unlink = v9fs_vfs_unlink,
0979     .mkdir = v9fs_vfs_mkdir_dotl,
0980     .rmdir = v9fs_vfs_rmdir,
0981     .mknod = v9fs_vfs_mknod_dotl,
0982     .rename = v9fs_vfs_rename,
0983     .getattr = v9fs_vfs_getattr_dotl,
0984     .setattr = v9fs_vfs_setattr_dotl,
0985     .listxattr = v9fs_listxattr,
0986     .get_acl = v9fs_iop_get_acl,
0987 };
0988 
0989 const struct inode_operations v9fs_file_inode_operations_dotl = {
0990     .getattr = v9fs_vfs_getattr_dotl,
0991     .setattr = v9fs_vfs_setattr_dotl,
0992     .listxattr = v9fs_listxattr,
0993     .get_acl = v9fs_iop_get_acl,
0994 };
0995 
0996 const struct inode_operations v9fs_symlink_inode_operations_dotl = {
0997     .get_link = v9fs_vfs_get_link_dotl,
0998     .getattr = v9fs_vfs_getattr_dotl,
0999     .setattr = v9fs_vfs_setattr_dotl,
1000     .listxattr = v9fs_listxattr,
1001 };