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 71d2d1ea93SAl Viro * @flags: flags propagated from v9fs_mount() 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; 896b365604SAneesh Kumar K.V if (v9ses->cache) 906b365604SAneesh Kumar K.V sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE; 919e82cf6aSEric Van Hensbergen 92db5841d4SAneesh Kumar K.V sb->s_flags = flags | MS_ACTIVE | MS_DIRSYNC | MS_NOATIME; 93db5841d4SAneesh Kumar K.V if (!v9ses->cache) 94db5841d4SAneesh Kumar K.V sb->s_flags |= MS_SYNCHRONOUS; 954b53e4b5SAbhishek Kulkarni 9685ff872dSAneesh Kumar K.V #ifdef CONFIG_9P_FS_POSIX_ACL 97e782ef71SVenkateswararao Jujjuri (JV) if ((v9ses->flags & V9FS_ACL_MASK) == V9FS_POSIX_ACL) 9885ff872dSAneesh Kumar K.V sb->s_flags |= MS_POSIXACL; 9985ff872dSAneesh Kumar K.V #endif 10085ff872dSAneesh Kumar K.V 1014b53e4b5SAbhishek Kulkarni save_mount_options(sb, data); 1029e82cf6aSEric Van Hensbergen } 1039e82cf6aSEric Van Hensbergen 1049e82cf6aSEric Van Hensbergen /** 105d2d1ea93SAl Viro * v9fs_mount - mount a superblock 1069e82cf6aSEric Van Hensbergen * @fs_type: file system type 1079e82cf6aSEric Van Hensbergen * @flags: mount flags 1089e82cf6aSEric Van Hensbergen * @dev_name: device name that was mounted 1099e82cf6aSEric Van Hensbergen * @data: mount options 1109e82cf6aSEric Van Hensbergen * 1119e82cf6aSEric Van Hensbergen */ 1129e82cf6aSEric Van Hensbergen 113d2d1ea93SAl Viro static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, 114d2d1ea93SAl Viro const char *dev_name, void *data) 1159e82cf6aSEric Van Hensbergen { 1169e82cf6aSEric Van Hensbergen struct super_block *sb = NULL; 1179e82cf6aSEric Van Hensbergen struct inode *inode = NULL; 1189e82cf6aSEric Van Hensbergen struct dentry *root = NULL; 1199e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = NULL; 1209e82cf6aSEric Van Hensbergen int mode = S_IRWXUGO | S_ISVTX; 121bd238fb4SLatchesar Ionkov struct p9_fid *fid; 1229e82cf6aSEric Van Hensbergen int retval = 0; 1239e82cf6aSEric Van Hensbergen 124bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, " \n"); 1259e82cf6aSEric Van Hensbergen 1261dac06b2SLatchesar Ionkov v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 1279e82cf6aSEric Van Hensbergen if (!v9ses) 128d2d1ea93SAl Viro return ERR_PTR(-ENOMEM); 1299e82cf6aSEric Van Hensbergen 130bd238fb4SLatchesar Ionkov fid = v9fs_session_init(v9ses, dev_name, data); 131bd238fb4SLatchesar Ionkov if (IS_ERR(fid)) { 132bd238fb4SLatchesar Ionkov retval = PTR_ERR(fid); 1335c25f347SAneesh Kumar K.V /* 1345c25f347SAneesh Kumar K.V * we need to call session_close to tear down some 1355c25f347SAneesh Kumar K.V * of the data structure setup by session_init 1365c25f347SAneesh Kumar K.V */ 137887b3eceSEric Van Hensbergen goto close_session; 138bd238fb4SLatchesar Ionkov } 139bd238fb4SLatchesar Ionkov 1409e82cf6aSEric Van Hensbergen sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 141454e2398SDavid Howells if (IS_ERR(sb)) { 142454e2398SDavid Howells retval = PTR_ERR(sb); 143f0853122SSripathi Kodi goto clunk_fid; 144454e2398SDavid Howells } 1454b53e4b5SAbhishek Kulkarni v9fs_fill_super(sb, v9ses, flags, data); 1469e82cf6aSEric Van Hensbergen 14798cd3fb0SAl Viro if (v9ses->cache) 14898cd3fb0SAl Viro sb->s_d_op = &v9fs_cached_dentry_operations; 14998cd3fb0SAl Viro else 15098cd3fb0SAl Viro sb->s_d_op = &v9fs_dentry_operations; 15198cd3fb0SAl Viro 1529e82cf6aSEric Van Hensbergen inode = v9fs_get_inode(sb, S_IFDIR | mode); 1539e82cf6aSEric Van Hensbergen if (IS_ERR(inode)) { 1549e82cf6aSEric Van Hensbergen retval = PTR_ERR(inode); 155887b3eceSEric Van Hensbergen goto release_sb; 1569e82cf6aSEric Van Hensbergen } 1579e82cf6aSEric Van Hensbergen root = d_alloc_root(inode); 1589e82cf6aSEric Van Hensbergen if (!root) { 159c96f5857SAl Viro iput(inode); 1609e82cf6aSEric Van Hensbergen retval = -ENOMEM; 161887b3eceSEric Van Hensbergen goto release_sb; 1629e82cf6aSEric Van Hensbergen } 1639e82cf6aSEric Van Hensbergen sb->s_root = root; 164f0853122SSripathi Kodi if (v9fs_proto_dotl(v9ses)) { 165f0853122SSripathi Kodi struct p9_stat_dotl *st = NULL; 166f0853122SSripathi Kodi st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 167f0853122SSripathi Kodi if (IS_ERR(st)) { 168f0853122SSripathi Kodi retval = PTR_ERR(st); 1695c25f347SAneesh Kumar K.V goto release_sb; 170f0853122SSripathi Kodi } 171f0853122SSripathi Kodi 172f0853122SSripathi Kodi v9fs_stat2inode_dotl(st, root->d_inode); 173f0853122SSripathi Kodi kfree(st); 174f0853122SSripathi Kodi } else { 175f0853122SSripathi Kodi struct p9_wstat *st = NULL; 176f0853122SSripathi Kodi st = p9_client_stat(fid); 177f0853122SSripathi Kodi if (IS_ERR(st)) { 178f0853122SSripathi Kodi retval = PTR_ERR(st); 1795c25f347SAneesh Kumar K.V goto release_sb; 180f0853122SSripathi Kodi } 181f0853122SSripathi Kodi 182f0853122SSripathi Kodi root->d_inode->i_ino = v9fs_qid2ino(&st->qid); 183bd238fb4SLatchesar Ionkov v9fs_stat2inode(st, root->d_inode, sb); 18451a87c55SEric Van Hensbergen 18551a87c55SEric Van Hensbergen p9stat_free(st); 186dda6b022SLatchesar Ionkov kfree(st); 187f0853122SSripathi Kodi } 18800ea2df4SAneesh Kumar K.V v9fs_fid_add(root, fid); 18985ff872dSAneesh Kumar K.V retval = v9fs_get_acl(inode, fid); 19085ff872dSAneesh Kumar K.V if (retval) 19185ff872dSAneesh Kumar K.V goto release_sb; 19200ea2df4SAneesh Kumar K.V /* 19300ea2df4SAneesh Kumar K.V * Add the root fid to session info. This is used 19400ea2df4SAneesh Kumar K.V * for file system sync. We want a cloned fid here 19500ea2df4SAneesh Kumar K.V * so that we can do a sync_filesystem after a 19600ea2df4SAneesh Kumar K.V * shrink_dcache_for_umount 19700ea2df4SAneesh Kumar K.V */ 19800ea2df4SAneesh Kumar K.V v9ses->root_fid = v9fs_fid_clone(root); 19900ea2df4SAneesh Kumar K.V if (IS_ERR(v9ses->root_fid)) { 20000ea2df4SAneesh Kumar K.V retval = PTR_ERR(v9ses->root_fid); 20100ea2df4SAneesh Kumar K.V goto release_sb; 20200ea2df4SAneesh Kumar K.V } 2039e82cf6aSEric Van Hensbergen 204a3ec947cSSukadev Bhattiprolu P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); 205d2d1ea93SAl Viro return dget(sb->s_root); 2069e82cf6aSEric Van Hensbergen 207887b3eceSEric Van Hensbergen clunk_fid: 208887b3eceSEric Van Hensbergen p9_client_clunk(fid); 209887b3eceSEric Van Hensbergen close_session: 210887b3eceSEric Van Hensbergen v9fs_session_close(v9ses); 211887b3eceSEric Van Hensbergen kfree(v9ses); 212d2d1ea93SAl Viro return ERR_PTR(retval); 2131b5ab3e8SAbhishek Kulkarni release_sb: 2145c25f347SAneesh Kumar K.V /* 21500ea2df4SAneesh Kumar K.V * we will do the session_close and root dentry 21600ea2df4SAneesh Kumar K.V * release in the below call. 2175c25f347SAneesh Kumar K.V */ 2181b5ab3e8SAbhishek Kulkarni deactivate_locked_super(sb); 219d2d1ea93SAl Viro return ERR_PTR(retval); 2209e82cf6aSEric Van Hensbergen } 2219e82cf6aSEric Van Hensbergen 2229e82cf6aSEric Van Hensbergen /** 2239e82cf6aSEric Van Hensbergen * v9fs_kill_super - Kill Superblock 2249e82cf6aSEric Van Hensbergen * @s: superblock 2259e82cf6aSEric Van Hensbergen * 2269e82cf6aSEric Van Hensbergen */ 2279e82cf6aSEric Van Hensbergen 2289e82cf6aSEric Van Hensbergen static void v9fs_kill_super(struct super_block *s) 2299e82cf6aSEric Van Hensbergen { 2309e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = s->s_fs_info; 2319e82cf6aSEric Van Hensbergen 232bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); 2339e82cf6aSEric Van Hensbergen 2349e82cf6aSEric Van Hensbergen kill_anon_super(s); 23500ea2df4SAneesh Kumar K.V p9_client_clunk(v9ses->root_fid); 2366d96d3abSAneesh Kumar K.V v9fs_session_cancel(v9ses); 2379e82cf6aSEric Van Hensbergen v9fs_session_close(v9ses); 2389e82cf6aSEric Van Hensbergen kfree(v9ses); 2391b5ab3e8SAbhishek Kulkarni s->s_fs_info = NULL; 240bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); 2419e82cf6aSEric Van Hensbergen } 2429e82cf6aSEric Van Hensbergen 243322b329aSEric Van Hensbergen static void 24442faad99SAl Viro v9fs_umount_begin(struct super_block *sb) 245322b329aSEric Van Hensbergen { 24667e55205SAlessio Igor Bogani struct v9fs_session_info *v9ses; 247322b329aSEric Van Hensbergen 24867e55205SAlessio Igor Bogani v9ses = sb->s_fs_info; 2496d96d3abSAneesh Kumar K.V v9fs_session_begin_cancel(v9ses); 250322b329aSEric Van Hensbergen } 251322b329aSEric Van Hensbergen 252bda8e775SSripathi Kodi static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) 253bda8e775SSripathi Kodi { 254bda8e775SSripathi Kodi struct v9fs_session_info *v9ses; 255bda8e775SSripathi Kodi struct p9_fid *fid; 256bda8e775SSripathi Kodi struct p9_rstatfs rs; 257bda8e775SSripathi Kodi int res; 258bda8e775SSripathi Kodi 259bda8e775SSripathi Kodi fid = v9fs_fid_lookup(dentry); 260bda8e775SSripathi Kodi if (IS_ERR(fid)) { 261bda8e775SSripathi Kodi res = PTR_ERR(fid); 262bda8e775SSripathi Kodi goto done; 263bda8e775SSripathi Kodi } 264bda8e775SSripathi Kodi 265bda8e775SSripathi Kodi v9ses = v9fs_inode2v9ses(dentry->d_inode); 266bda8e775SSripathi Kodi if (v9fs_proto_dotl(v9ses)) { 267bda8e775SSripathi Kodi res = p9_client_statfs(fid, &rs); 268bda8e775SSripathi Kodi if (res == 0) { 269368c09d2SM. Mohan Kumar buf->f_type = V9FS_MAGIC; 270bda8e775SSripathi Kodi buf->f_bsize = rs.bsize; 271bda8e775SSripathi Kodi buf->f_blocks = rs.blocks; 272bda8e775SSripathi Kodi buf->f_bfree = rs.bfree; 273bda8e775SSripathi Kodi buf->f_bavail = rs.bavail; 274bda8e775SSripathi Kodi buf->f_files = rs.files; 275bda8e775SSripathi Kodi buf->f_ffree = rs.ffree; 276bda8e775SSripathi Kodi buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; 277bda8e775SSripathi Kodi buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; 278bda8e775SSripathi Kodi buf->f_namelen = rs.namelen; 279bda8e775SSripathi Kodi } 280bda8e775SSripathi Kodi if (res != -ENOSYS) 281bda8e775SSripathi Kodi goto done; 282bda8e775SSripathi Kodi } 283bda8e775SSripathi Kodi res = simple_statfs(dentry, buf); 284bda8e775SSripathi Kodi done: 285bda8e775SSripathi Kodi return res; 286bda8e775SSripathi Kodi } 287bda8e775SSripathi Kodi 28800ea2df4SAneesh Kumar K.V static int v9fs_sync_fs(struct super_block *sb, int wait) 28900ea2df4SAneesh Kumar K.V { 29000ea2df4SAneesh Kumar K.V struct v9fs_session_info *v9ses = sb->s_fs_info; 29100ea2df4SAneesh Kumar K.V 29200ea2df4SAneesh Kumar K.V P9_DPRINTK(P9_DEBUG_VFS, "v9fs_sync_fs: super_block %p\n", sb); 29300ea2df4SAneesh Kumar K.V return p9_client_sync_fs(v9ses->root_fid); 29400ea2df4SAneesh Kumar K.V } 29500ea2df4SAneesh Kumar K.V 296ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations v9fs_super_ops = { 29760e78d2cSAbhishek Kulkarni .alloc_inode = v9fs_alloc_inode, 29860e78d2cSAbhishek Kulkarni .destroy_inode = v9fs_destroy_inode, 2999e82cf6aSEric Van Hensbergen .statfs = simple_statfs, 300b57922d9SAl Viro .evict_inode = v9fs_evict_inode, 3014b53e4b5SAbhishek Kulkarni .show_options = generic_show_options, 302322b329aSEric Van Hensbergen .umount_begin = v9fs_umount_begin, 3039e82cf6aSEric Van Hensbergen }; 3049e82cf6aSEric Van Hensbergen 3059b6533c9SSripathi Kodi static const struct super_operations v9fs_super_ops_dotl = { 3069b6533c9SSripathi Kodi .alloc_inode = v9fs_alloc_inode, 3079b6533c9SSripathi Kodi .destroy_inode = v9fs_destroy_inode, 30800ea2df4SAneesh Kumar K.V .sync_fs = v9fs_sync_fs, 309bda8e775SSripathi Kodi .statfs = v9fs_statfs, 310b57922d9SAl Viro .evict_inode = v9fs_evict_inode, 3119b6533c9SSripathi Kodi .show_options = generic_show_options, 3129b6533c9SSripathi Kodi .umount_begin = v9fs_umount_begin, 3139b6533c9SSripathi Kodi }; 3149b6533c9SSripathi Kodi 3159e82cf6aSEric Van Hensbergen struct file_system_type v9fs_fs_type = { 31667543e50SEric Van Hensbergen .name = "9p", 317d2d1ea93SAl Viro .mount = v9fs_mount, 3189e82cf6aSEric Van Hensbergen .kill_sb = v9fs_kill_super, 3199e82cf6aSEric Van Hensbergen .owner = THIS_MODULE, 320a534c8d1SAneesh Kumar K.V .fs_flags = FS_RENAME_DOES_D_MOVE, 3219e82cf6aSEric Van Hensbergen }; 322