19e82cf6aSEric Van Hensbergen /* 29e82cf6aSEric Van Hensbergen * linux/fs/9p/vfs_super.c 39e82cf6aSEric Van Hensbergen * 49e82cf6aSEric Van Hensbergen * This file contians superblock ops for 9P2000. It is intended that 59e82cf6aSEric Van Hensbergen * you mount this file system on directories. 69e82cf6aSEric Van Hensbergen * 79e82cf6aSEric Van Hensbergen * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 89e82cf6aSEric Van Hensbergen * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 99e82cf6aSEric Van Hensbergen * 109e82cf6aSEric Van Hensbergen * This program is free software; you can redistribute it and/or modify 1142e8c509SEric Van Hensbergen * it under the terms of the GNU General Public License version 2 1242e8c509SEric Van Hensbergen * as published by the Free Software Foundation. 139e82cf6aSEric Van Hensbergen * 149e82cf6aSEric Van Hensbergen * This program is distributed in the hope that it will be useful, 159e82cf6aSEric Van Hensbergen * but WITHOUT ANY WARRANTY; without even the implied warranty of 169e82cf6aSEric Van Hensbergen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 179e82cf6aSEric Van Hensbergen * GNU General Public License for more details. 189e82cf6aSEric Van Hensbergen * 199e82cf6aSEric Van Hensbergen * You should have received a copy of the GNU General Public License 209e82cf6aSEric Van Hensbergen * along with this program; if not, write to: 219e82cf6aSEric Van Hensbergen * Free Software Foundation 229e82cf6aSEric Van Hensbergen * 51 Franklin Street, Fifth Floor 239e82cf6aSEric Van Hensbergen * Boston, MA 02111-1301 USA 249e82cf6aSEric Van Hensbergen * 259e82cf6aSEric Van Hensbergen */ 269e82cf6aSEric Van Hensbergen 279e82cf6aSEric Van Hensbergen #include <linux/kernel.h> 289e82cf6aSEric Van Hensbergen #include <linux/module.h> 299e82cf6aSEric Van Hensbergen #include <linux/errno.h> 309e82cf6aSEric Van Hensbergen #include <linux/fs.h> 319e82cf6aSEric Van Hensbergen #include <linux/file.h> 329e82cf6aSEric Van Hensbergen #include <linux/stat.h> 339e82cf6aSEric Van Hensbergen #include <linux/string.h> 349e82cf6aSEric Van Hensbergen #include <linux/inet.h> 359e82cf6aSEric Van Hensbergen #include <linux/pagemap.h> 369e82cf6aSEric Van Hensbergen #include <linux/seq_file.h> 379e82cf6aSEric Van Hensbergen #include <linux/mount.h> 389e82cf6aSEric Van Hensbergen #include <linux/idr.h> 39e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 405a0e3ad6STejun Heo #include <linux/slab.h> 41bda8e775SSripathi Kodi #include <linux/statfs.h> 42368c09d2SM. Mohan Kumar #include <linux/magic.h> 43bd238fb4SLatchesar Ionkov #include <net/9p/9p.h> 44bd238fb4SLatchesar Ionkov #include <net/9p/client.h> 459e82cf6aSEric Van Hensbergen 469e82cf6aSEric Van Hensbergen #include "v9fs.h" 479e82cf6aSEric Van Hensbergen #include "v9fs_vfs.h" 489e82cf6aSEric Van Hensbergen #include "fid.h" 49ebf46264SAneesh Kumar K.V #include "xattr.h" 5085ff872dSAneesh Kumar K.V #include "acl.h" 519e82cf6aSEric Van Hensbergen 529b6533c9SSripathi Kodi static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; 539e82cf6aSEric Van Hensbergen 549e82cf6aSEric Van Hensbergen /** 559e82cf6aSEric Van Hensbergen * v9fs_set_super - set the superblock 569e82cf6aSEric Van Hensbergen * @s: super block 579e82cf6aSEric Van Hensbergen * @data: file system specific data 589e82cf6aSEric Van Hensbergen * 599e82cf6aSEric Van Hensbergen */ 609e82cf6aSEric Van Hensbergen 619e82cf6aSEric Van Hensbergen static int v9fs_set_super(struct super_block *s, void *data) 629e82cf6aSEric Van Hensbergen { 639e82cf6aSEric Van Hensbergen s->s_fs_info = data; 649e82cf6aSEric Van Hensbergen return set_anon_super(s, data); 659e82cf6aSEric Van Hensbergen } 669e82cf6aSEric Van Hensbergen 679e82cf6aSEric Van Hensbergen /** 689e82cf6aSEric Van Hensbergen * v9fs_fill_super - populate superblock with info 699e82cf6aSEric Van Hensbergen * @sb: superblock 709e82cf6aSEric Van Hensbergen * @v9ses: session information 71ee443996SEric Van Hensbergen * @flags: flags propagated from v9fs_get_sb() 729e82cf6aSEric Van Hensbergen * 739e82cf6aSEric Van Hensbergen */ 749e82cf6aSEric Van Hensbergen 759e82cf6aSEric Van Hensbergen static void 769e82cf6aSEric Van Hensbergen v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, 774b53e4b5SAbhishek Kulkarni int flags, void *data) 789e82cf6aSEric Van Hensbergen { 799e82cf6aSEric Van Hensbergen sb->s_maxbytes = MAX_LFS_FILESIZE; 809e82cf6aSEric Van Hensbergen sb->s_blocksize_bits = fls(v9ses->maxdata - 1); 819e82cf6aSEric Van Hensbergen sb->s_blocksize = 1 << sb->s_blocksize_bits; 829e82cf6aSEric Van Hensbergen sb->s_magic = V9FS_MAGIC; 83ebf46264SAneesh Kumar K.V if (v9fs_proto_dotl(v9ses)) { 849b6533c9SSripathi Kodi sb->s_op = &v9fs_super_ops_dotl; 85ebf46264SAneesh Kumar K.V sb->s_xattr = v9fs_xattr_handlers; 86ebf46264SAneesh Kumar K.V } else 879e82cf6aSEric Van Hensbergen sb->s_op = &v9fs_super_ops; 880ed07ddbSJens Axboe sb->s_bdi = &v9ses->bdi; 899e82cf6aSEric Van Hensbergen 909e82cf6aSEric Van Hensbergen sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | 910d456fa4SChristoph Hellwig MS_NOATIME; 924b53e4b5SAbhishek Kulkarni 9385ff872dSAneesh Kumar K.V #ifdef CONFIG_9P_FS_POSIX_ACL 9476381a42SAneesh Kumar K.V if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT) 9585ff872dSAneesh Kumar K.V sb->s_flags |= MS_POSIXACL; 9685ff872dSAneesh Kumar K.V #endif 9785ff872dSAneesh Kumar K.V 984b53e4b5SAbhishek Kulkarni save_mount_options(sb, data); 999e82cf6aSEric Van Hensbergen } 1009e82cf6aSEric Van Hensbergen 1019e82cf6aSEric Van Hensbergen /** 1029e82cf6aSEric Van Hensbergen * v9fs_get_sb - mount a superblock 1039e82cf6aSEric Van Hensbergen * @fs_type: file system type 1049e82cf6aSEric Van Hensbergen * @flags: mount flags 1059e82cf6aSEric Van Hensbergen * @dev_name: device name that was mounted 1069e82cf6aSEric Van Hensbergen * @data: mount options 107454e2398SDavid Howells * @mnt: mountpoint record to be instantiated 1089e82cf6aSEric Van Hensbergen * 1099e82cf6aSEric Van Hensbergen */ 1109e82cf6aSEric Van Hensbergen 111454e2398SDavid Howells static int v9fs_get_sb(struct file_system_type *fs_type, int flags, 112454e2398SDavid Howells const char *dev_name, void *data, 113454e2398SDavid Howells struct vfsmount *mnt) 1149e82cf6aSEric Van Hensbergen { 1159e82cf6aSEric Van Hensbergen struct super_block *sb = NULL; 1169e82cf6aSEric Van Hensbergen struct inode *inode = NULL; 1179e82cf6aSEric Van Hensbergen struct dentry *root = NULL; 1189e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = NULL; 1199e82cf6aSEric Van Hensbergen int mode = S_IRWXUGO | S_ISVTX; 120bd238fb4SLatchesar Ionkov struct p9_fid *fid; 1219e82cf6aSEric Van Hensbergen int retval = 0; 1229e82cf6aSEric Van Hensbergen 123bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, " \n"); 1249e82cf6aSEric Van Hensbergen 1251dac06b2SLatchesar Ionkov v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 1269e82cf6aSEric Van Hensbergen if (!v9ses) 127454e2398SDavid Howells return -ENOMEM; 1289e82cf6aSEric Van Hensbergen 129bd238fb4SLatchesar Ionkov fid = v9fs_session_init(v9ses, dev_name, data); 130bd238fb4SLatchesar Ionkov if (IS_ERR(fid)) { 131bd238fb4SLatchesar Ionkov retval = PTR_ERR(fid); 1325c25f347SAneesh Kumar K.V /* 1335c25f347SAneesh Kumar K.V * we need to call session_close to tear down some 1345c25f347SAneesh Kumar K.V * of the data structure setup by session_init 1355c25f347SAneesh Kumar K.V */ 136887b3eceSEric Van Hensbergen goto close_session; 137bd238fb4SLatchesar Ionkov } 138bd238fb4SLatchesar Ionkov 1399e82cf6aSEric Van Hensbergen sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 140454e2398SDavid Howells if (IS_ERR(sb)) { 141454e2398SDavid Howells retval = PTR_ERR(sb); 142f0853122SSripathi Kodi goto clunk_fid; 143454e2398SDavid Howells } 1444b53e4b5SAbhishek Kulkarni v9fs_fill_super(sb, v9ses, flags, data); 1459e82cf6aSEric Van Hensbergen 1469e82cf6aSEric Van Hensbergen inode = v9fs_get_inode(sb, S_IFDIR | mode); 1479e82cf6aSEric Van Hensbergen if (IS_ERR(inode)) { 1489e82cf6aSEric Van Hensbergen retval = PTR_ERR(inode); 149887b3eceSEric Van Hensbergen goto release_sb; 1509e82cf6aSEric Van Hensbergen } 1519e82cf6aSEric Van Hensbergen 1529e82cf6aSEric Van Hensbergen root = d_alloc_root(inode); 1539e82cf6aSEric Van Hensbergen if (!root) { 154c96f5857SAl Viro iput(inode); 1559e82cf6aSEric Van Hensbergen retval = -ENOMEM; 156887b3eceSEric Van Hensbergen goto release_sb; 1579e82cf6aSEric Van Hensbergen } 1589e82cf6aSEric Van Hensbergen sb->s_root = root; 159f0853122SSripathi Kodi if (v9fs_proto_dotl(v9ses)) { 160f0853122SSripathi Kodi struct p9_stat_dotl *st = NULL; 161f0853122SSripathi Kodi st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 162f0853122SSripathi Kodi if (IS_ERR(st)) { 163f0853122SSripathi Kodi retval = PTR_ERR(st); 1645c25f347SAneesh Kumar K.V goto release_sb; 165f0853122SSripathi Kodi } 166f0853122SSripathi Kodi 167f0853122SSripathi Kodi v9fs_stat2inode_dotl(st, root->d_inode); 168f0853122SSripathi Kodi kfree(st); 169f0853122SSripathi Kodi } else { 170f0853122SSripathi Kodi struct p9_wstat *st = NULL; 171f0853122SSripathi Kodi st = p9_client_stat(fid); 172f0853122SSripathi Kodi if (IS_ERR(st)) { 173f0853122SSripathi Kodi retval = PTR_ERR(st); 1745c25f347SAneesh Kumar K.V goto release_sb; 175f0853122SSripathi Kodi } 176f0853122SSripathi Kodi 177f0853122SSripathi Kodi root->d_inode->i_ino = v9fs_qid2ino(&st->qid); 178bd238fb4SLatchesar Ionkov v9fs_stat2inode(st, root->d_inode, sb); 17951a87c55SEric Van Hensbergen 18051a87c55SEric Van Hensbergen p9stat_free(st); 181dda6b022SLatchesar Ionkov kfree(st); 182f0853122SSripathi Kodi } 18385ff872dSAneesh Kumar K.V retval = v9fs_get_acl(inode, fid); 18485ff872dSAneesh Kumar K.V if (retval) 18585ff872dSAneesh Kumar K.V goto release_sb; 186f0853122SSripathi Kodi v9fs_fid_add(root, fid); 1879e82cf6aSEric Van Hensbergen 188a3ec947cSSukadev Bhattiprolu P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); 189a3ec947cSSukadev Bhattiprolu simple_set_mnt(mnt, sb); 190a3ec947cSSukadev Bhattiprolu return 0; 1919e82cf6aSEric Van Hensbergen 192887b3eceSEric Van Hensbergen clunk_fid: 193887b3eceSEric Van Hensbergen p9_client_clunk(fid); 194887b3eceSEric Van Hensbergen close_session: 195887b3eceSEric Van Hensbergen v9fs_session_close(v9ses); 196887b3eceSEric Van Hensbergen kfree(v9ses); 1971b5ab3e8SAbhishek Kulkarni return retval; 1981b5ab3e8SAbhishek Kulkarni release_sb: 1995c25f347SAneesh Kumar K.V /* 2005c25f347SAneesh Kumar K.V * we will do the session_close and root dentry release 2015c25f347SAneesh Kumar K.V * in the below call. But we need to clunk fid, because we haven't 2025c25f347SAneesh Kumar K.V * attached the fid to dentry so it won't get clunked 2035c25f347SAneesh Kumar K.V * automatically. 2045c25f347SAneesh Kumar K.V */ 2055c25f347SAneesh Kumar K.V p9_client_clunk(fid); 2061b5ab3e8SAbhishek Kulkarni deactivate_locked_super(sb); 207454e2398SDavid Howells return retval; 2089e82cf6aSEric Van Hensbergen } 2099e82cf6aSEric Van Hensbergen 2109e82cf6aSEric Van Hensbergen /** 2119e82cf6aSEric Van Hensbergen * v9fs_kill_super - Kill Superblock 2129e82cf6aSEric Van Hensbergen * @s: superblock 2139e82cf6aSEric Van Hensbergen * 2149e82cf6aSEric Van Hensbergen */ 2159e82cf6aSEric Van Hensbergen 2169e82cf6aSEric Van Hensbergen static void v9fs_kill_super(struct super_block *s) 2179e82cf6aSEric Van Hensbergen { 2189e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = s->s_fs_info; 2199e82cf6aSEric Van Hensbergen 220bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); 2219e82cf6aSEric Van Hensbergen 222083c73c2SAl Viro if (s->s_root) 2239e82cf6aSEric Van Hensbergen v9fs_dentry_release(s->s_root); /* clunk root */ 2249e82cf6aSEric Van Hensbergen 2259e82cf6aSEric Van Hensbergen kill_anon_super(s); 2269e82cf6aSEric Van Hensbergen 2276d96d3abSAneesh Kumar K.V v9fs_session_cancel(v9ses); 2289e82cf6aSEric Van Hensbergen v9fs_session_close(v9ses); 2299e82cf6aSEric Van Hensbergen kfree(v9ses); 2301b5ab3e8SAbhishek Kulkarni s->s_fs_info = NULL; 231bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); 2329e82cf6aSEric Van Hensbergen } 2339e82cf6aSEric Van Hensbergen 234322b329aSEric Van Hensbergen static void 23542faad99SAl Viro v9fs_umount_begin(struct super_block *sb) 236322b329aSEric Van Hensbergen { 23767e55205SAlessio Igor Bogani struct v9fs_session_info *v9ses; 238322b329aSEric Van Hensbergen 23967e55205SAlessio Igor Bogani v9ses = sb->s_fs_info; 2406d96d3abSAneesh Kumar K.V v9fs_session_begin_cancel(v9ses); 241322b329aSEric Van Hensbergen } 242322b329aSEric Van Hensbergen 243bda8e775SSripathi Kodi static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) 244bda8e775SSripathi Kodi { 245bda8e775SSripathi Kodi struct v9fs_session_info *v9ses; 246bda8e775SSripathi Kodi struct p9_fid *fid; 247bda8e775SSripathi Kodi struct p9_rstatfs rs; 248bda8e775SSripathi Kodi int res; 249bda8e775SSripathi Kodi 250bda8e775SSripathi Kodi fid = v9fs_fid_lookup(dentry); 251bda8e775SSripathi Kodi if (IS_ERR(fid)) { 252bda8e775SSripathi Kodi res = PTR_ERR(fid); 253bda8e775SSripathi Kodi goto done; 254bda8e775SSripathi Kodi } 255bda8e775SSripathi Kodi 256bda8e775SSripathi Kodi v9ses = v9fs_inode2v9ses(dentry->d_inode); 257bda8e775SSripathi Kodi if (v9fs_proto_dotl(v9ses)) { 258bda8e775SSripathi Kodi res = p9_client_statfs(fid, &rs); 259bda8e775SSripathi Kodi if (res == 0) { 260368c09d2SM. Mohan Kumar buf->f_type = V9FS_MAGIC; 261bda8e775SSripathi Kodi buf->f_bsize = rs.bsize; 262bda8e775SSripathi Kodi buf->f_blocks = rs.blocks; 263bda8e775SSripathi Kodi buf->f_bfree = rs.bfree; 264bda8e775SSripathi Kodi buf->f_bavail = rs.bavail; 265bda8e775SSripathi Kodi buf->f_files = rs.files; 266bda8e775SSripathi Kodi buf->f_ffree = rs.ffree; 267bda8e775SSripathi Kodi buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; 268bda8e775SSripathi Kodi buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; 269bda8e775SSripathi Kodi buf->f_namelen = rs.namelen; 270bda8e775SSripathi Kodi } 271bda8e775SSripathi Kodi if (res != -ENOSYS) 272bda8e775SSripathi Kodi goto done; 273bda8e775SSripathi Kodi } 274bda8e775SSripathi Kodi res = simple_statfs(dentry, buf); 275bda8e775SSripathi Kodi done: 276bda8e775SSripathi Kodi return res; 277bda8e775SSripathi Kodi } 278bda8e775SSripathi Kodi 279ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations v9fs_super_ops = { 28060e78d2cSAbhishek Kulkarni #ifdef CONFIG_9P_FSCACHE 28160e78d2cSAbhishek Kulkarni .alloc_inode = v9fs_alloc_inode, 28260e78d2cSAbhishek Kulkarni .destroy_inode = v9fs_destroy_inode, 28360e78d2cSAbhishek Kulkarni #endif 2849e82cf6aSEric Van Hensbergen .statfs = simple_statfs, 285b57922d9SAl Viro .evict_inode = v9fs_evict_inode, 2864b53e4b5SAbhishek Kulkarni .show_options = generic_show_options, 287322b329aSEric Van Hensbergen .umount_begin = v9fs_umount_begin, 2889e82cf6aSEric Van Hensbergen }; 2899e82cf6aSEric Van Hensbergen 2909b6533c9SSripathi Kodi static const struct super_operations v9fs_super_ops_dotl = { 2919b6533c9SSripathi Kodi #ifdef CONFIG_9P_FSCACHE 2929b6533c9SSripathi Kodi .alloc_inode = v9fs_alloc_inode, 2939b6533c9SSripathi Kodi .destroy_inode = v9fs_destroy_inode, 2949b6533c9SSripathi Kodi #endif 295bda8e775SSripathi Kodi .statfs = v9fs_statfs, 296b57922d9SAl Viro .evict_inode = v9fs_evict_inode, 2979b6533c9SSripathi Kodi .show_options = generic_show_options, 2989b6533c9SSripathi Kodi .umount_begin = v9fs_umount_begin, 2999b6533c9SSripathi Kodi }; 3009b6533c9SSripathi Kodi 3019e82cf6aSEric Van Hensbergen struct file_system_type v9fs_fs_type = { 30267543e50SEric Van Hensbergen .name = "9p", 3039e82cf6aSEric Van Hensbergen .get_sb = v9fs_get_sb, 3049e82cf6aSEric Van Hensbergen .kill_sb = v9fs_kill_super, 3059e82cf6aSEric Van Hensbergen .owner = THIS_MODULE, 306a534c8d1SAneesh Kumar K.V .fs_flags = FS_RENAME_DOES_D_MOVE, 3079e82cf6aSEric Van Hensbergen }; 308