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> 40bd238fb4SLatchesar Ionkov #include <net/9p/9p.h> 41bd238fb4SLatchesar Ionkov #include <net/9p/client.h> 429e82cf6aSEric Van Hensbergen 439e82cf6aSEric Van Hensbergen #include "v9fs.h" 449e82cf6aSEric Van Hensbergen #include "v9fs_vfs.h" 459e82cf6aSEric Van Hensbergen #include "fid.h" 469e82cf6aSEric Van Hensbergen 479e82cf6aSEric Van Hensbergen static void v9fs_clear_inode(struct inode *); 48ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations v9fs_super_ops; 499e82cf6aSEric Van Hensbergen 509e82cf6aSEric Van Hensbergen /** 519e82cf6aSEric Van Hensbergen * v9fs_clear_inode - release an inode 529e82cf6aSEric Van Hensbergen * @inode: inode to release 539e82cf6aSEric Van Hensbergen * 549e82cf6aSEric Van Hensbergen */ 559e82cf6aSEric Van Hensbergen 569e82cf6aSEric Van Hensbergen static void v9fs_clear_inode(struct inode *inode) 579e82cf6aSEric Van Hensbergen { 589e82cf6aSEric Van Hensbergen filemap_fdatawrite(inode->i_mapping); 599e82cf6aSEric Van Hensbergen } 609e82cf6aSEric Van Hensbergen 619e82cf6aSEric Van Hensbergen /** 629e82cf6aSEric Van Hensbergen * v9fs_set_super - set the superblock 639e82cf6aSEric Van Hensbergen * @s: super block 649e82cf6aSEric Van Hensbergen * @data: file system specific data 659e82cf6aSEric Van Hensbergen * 669e82cf6aSEric Van Hensbergen */ 679e82cf6aSEric Van Hensbergen 689e82cf6aSEric Van Hensbergen static int v9fs_set_super(struct super_block *s, void *data) 699e82cf6aSEric Van Hensbergen { 709e82cf6aSEric Van Hensbergen s->s_fs_info = data; 719e82cf6aSEric Van Hensbergen return set_anon_super(s, data); 729e82cf6aSEric Van Hensbergen } 739e82cf6aSEric Van Hensbergen 749e82cf6aSEric Van Hensbergen /** 759e82cf6aSEric Van Hensbergen * v9fs_fill_super - populate superblock with info 769e82cf6aSEric Van Hensbergen * @sb: superblock 779e82cf6aSEric Van Hensbergen * @v9ses: session information 78ee443996SEric Van Hensbergen * @flags: flags propagated from v9fs_get_sb() 799e82cf6aSEric Van Hensbergen * 809e82cf6aSEric Van Hensbergen */ 819e82cf6aSEric Van Hensbergen 829e82cf6aSEric Van Hensbergen static void 839e82cf6aSEric Van Hensbergen v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, 849e82cf6aSEric Van Hensbergen int flags) 859e82cf6aSEric Van Hensbergen { 869e82cf6aSEric Van Hensbergen sb->s_maxbytes = MAX_LFS_FILESIZE; 879e82cf6aSEric Van Hensbergen sb->s_blocksize_bits = fls(v9ses->maxdata - 1); 889e82cf6aSEric Van Hensbergen sb->s_blocksize = 1 << sb->s_blocksize_bits; 899e82cf6aSEric Van Hensbergen sb->s_magic = V9FS_MAGIC; 909e82cf6aSEric Van Hensbergen sb->s_op = &v9fs_super_ops; 919e82cf6aSEric Van Hensbergen 929e82cf6aSEric Van Hensbergen sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | 930d456fa4SChristoph Hellwig MS_NOATIME; 949e82cf6aSEric Van Hensbergen } 959e82cf6aSEric Van Hensbergen 969e82cf6aSEric Van Hensbergen /** 979e82cf6aSEric Van Hensbergen * v9fs_get_sb - mount a superblock 989e82cf6aSEric Van Hensbergen * @fs_type: file system type 999e82cf6aSEric Van Hensbergen * @flags: mount flags 1009e82cf6aSEric Van Hensbergen * @dev_name: device name that was mounted 1019e82cf6aSEric Van Hensbergen * @data: mount options 102454e2398SDavid Howells * @mnt: mountpoint record to be instantiated 1039e82cf6aSEric Van Hensbergen * 1049e82cf6aSEric Van Hensbergen */ 1059e82cf6aSEric Van Hensbergen 106454e2398SDavid Howells static int v9fs_get_sb(struct file_system_type *fs_type, int flags, 107454e2398SDavid Howells const char *dev_name, void *data, 108454e2398SDavid Howells struct vfsmount *mnt) 1099e82cf6aSEric Van Hensbergen { 1109e82cf6aSEric Van Hensbergen struct super_block *sb = NULL; 1119e82cf6aSEric Van Hensbergen struct inode *inode = NULL; 1129e82cf6aSEric Van Hensbergen struct dentry *root = NULL; 1139e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = NULL; 114bd238fb4SLatchesar Ionkov struct p9_stat *st = NULL; 1159e82cf6aSEric Van Hensbergen int mode = S_IRWXUGO | S_ISVTX; 1169e82cf6aSEric Van Hensbergen uid_t uid = current->fsuid; 1179e82cf6aSEric Van Hensbergen gid_t gid = current->fsgid; 118bd238fb4SLatchesar Ionkov struct p9_fid *fid; 1199e82cf6aSEric Van Hensbergen int retval = 0; 1209e82cf6aSEric Van Hensbergen 121bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, " \n"); 1229e82cf6aSEric Van Hensbergen 123dda6b022SLatchesar Ionkov st = NULL; 1241dac06b2SLatchesar Ionkov v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 1259e82cf6aSEric Van Hensbergen if (!v9ses) 126454e2398SDavid Howells return -ENOMEM; 1279e82cf6aSEric Van Hensbergen 128bd238fb4SLatchesar Ionkov fid = v9fs_session_init(v9ses, dev_name, data); 129bd238fb4SLatchesar Ionkov if (IS_ERR(fid)) { 130bd238fb4SLatchesar Ionkov retval = PTR_ERR(fid); 131bd238fb4SLatchesar Ionkov fid = NULL; 132bd238fb4SLatchesar Ionkov kfree(v9ses); 133bd238fb4SLatchesar Ionkov v9ses = NULL; 134bd238fb4SLatchesar Ionkov goto error; 135bd238fb4SLatchesar Ionkov } 136bd238fb4SLatchesar Ionkov 137bd238fb4SLatchesar Ionkov st = p9_client_stat(fid); 138bd238fb4SLatchesar Ionkov if (IS_ERR(st)) { 139bd238fb4SLatchesar Ionkov retval = PTR_ERR(st); 140bd238fb4SLatchesar Ionkov goto error; 1419e82cf6aSEric Van Hensbergen } 1429e82cf6aSEric Van Hensbergen 1439e82cf6aSEric Van Hensbergen sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 144454e2398SDavid Howells if (IS_ERR(sb)) { 145454e2398SDavid Howells retval = PTR_ERR(sb); 146bd238fb4SLatchesar Ionkov goto error; 147454e2398SDavid Howells } 1489e82cf6aSEric Van Hensbergen v9fs_fill_super(sb, v9ses, flags); 1499e82cf6aSEric Van Hensbergen 1509e82cf6aSEric Van Hensbergen inode = v9fs_get_inode(sb, S_IFDIR | mode); 1519e82cf6aSEric Van Hensbergen if (IS_ERR(inode)) { 1529e82cf6aSEric Van Hensbergen retval = PTR_ERR(inode); 153bd238fb4SLatchesar Ionkov goto error; 1549e82cf6aSEric Van Hensbergen } 1559e82cf6aSEric Van Hensbergen 1569e82cf6aSEric Van Hensbergen inode->i_uid = uid; 1579e82cf6aSEric Van Hensbergen inode->i_gid = gid; 1589e82cf6aSEric Van Hensbergen 1599e82cf6aSEric Van Hensbergen root = d_alloc_root(inode); 1609e82cf6aSEric Van Hensbergen if (!root) { 1619e82cf6aSEric Van Hensbergen retval = -ENOMEM; 162bd238fb4SLatchesar Ionkov goto error; 1639e82cf6aSEric Van Hensbergen } 1649e82cf6aSEric Van Hensbergen 1659e82cf6aSEric Van Hensbergen sb->s_root = root; 166bd238fb4SLatchesar Ionkov root->d_inode->i_ino = v9fs_qid2ino(&st->qid); 167bd238fb4SLatchesar Ionkov v9fs_stat2inode(st, root->d_inode, sb); 168bd238fb4SLatchesar Ionkov v9fs_fid_add(root, fid); 169dda6b022SLatchesar Ionkov kfree(st); 1709e82cf6aSEric Van Hensbergen 171454e2398SDavid Howells return simple_set_mnt(mnt, sb); 1729e82cf6aSEric Van Hensbergen 173bd238fb4SLatchesar Ionkov error: 174dda6b022SLatchesar Ionkov kfree(st); 175bd238fb4SLatchesar Ionkov if (fid) 176bd238fb4SLatchesar Ionkov p9_client_clunk(fid); 17700fbc6dfSEric Van Hensbergen 178bd238fb4SLatchesar Ionkov if (v9ses) { 179bd238fb4SLatchesar Ionkov v9fs_session_close(v9ses); 180bd238fb4SLatchesar Ionkov kfree(v9ses); 181bd238fb4SLatchesar Ionkov } 182bd238fb4SLatchesar Ionkov 183bd238fb4SLatchesar Ionkov if (sb) { 1849e82cf6aSEric Van Hensbergen up_write(&sb->s_umount); 1859e82cf6aSEric Van Hensbergen deactivate_super(sb); 186bd238fb4SLatchesar Ionkov } 187bd238fb4SLatchesar Ionkov 188454e2398SDavid Howells return retval; 1899e82cf6aSEric Van Hensbergen } 1909e82cf6aSEric Van Hensbergen 1919e82cf6aSEric Van Hensbergen /** 1929e82cf6aSEric Van Hensbergen * v9fs_kill_super - Kill Superblock 1939e82cf6aSEric Van Hensbergen * @s: superblock 1949e82cf6aSEric Van Hensbergen * 1959e82cf6aSEric Van Hensbergen */ 1969e82cf6aSEric Van Hensbergen 1979e82cf6aSEric Van Hensbergen static void v9fs_kill_super(struct super_block *s) 1989e82cf6aSEric Van Hensbergen { 1999e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = s->s_fs_info; 2009e82cf6aSEric Van Hensbergen 201bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); 2029e82cf6aSEric Van Hensbergen 2039e82cf6aSEric Van Hensbergen v9fs_dentry_release(s->s_root); /* clunk root */ 2049e82cf6aSEric Van Hensbergen 2059e82cf6aSEric Van Hensbergen kill_anon_super(s); 2069e82cf6aSEric Van Hensbergen 2079e82cf6aSEric Van Hensbergen v9fs_session_close(v9ses); 2089e82cf6aSEric Van Hensbergen kfree(v9ses); 209bd238fb4SLatchesar Ionkov P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); 2109e82cf6aSEric Van Hensbergen } 2119e82cf6aSEric Van Hensbergen 2129e82cf6aSEric Van Hensbergen /** 2139e82cf6aSEric Van Hensbergen * v9fs_show_options - Show mount options in /proc/mounts 2149e82cf6aSEric Van Hensbergen * @m: seq_file to write to 2159e82cf6aSEric Van Hensbergen * @mnt: mount descriptor 2169e82cf6aSEric Van Hensbergen * 2179e82cf6aSEric Van Hensbergen */ 2189e82cf6aSEric Van Hensbergen 2199e82cf6aSEric Van Hensbergen static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt) 2209e82cf6aSEric Van Hensbergen { 2219e82cf6aSEric Van Hensbergen struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; 2229e82cf6aSEric Van Hensbergen 223a80d923eSEric Van Hensbergen seq_printf(m, "%s", v9ses->options); 2249e82cf6aSEric Van Hensbergen return 0; 2259e82cf6aSEric Van Hensbergen } 2269e82cf6aSEric Van Hensbergen 227322b329aSEric Van Hensbergen static void 22842faad99SAl Viro v9fs_umount_begin(struct super_block *sb) 229322b329aSEric Van Hensbergen { 23042faad99SAl Viro struct v9fs_session_info *v9ses = sb->s_fs_info; 231322b329aSEric Van Hensbergen 232322b329aSEric Van Hensbergen v9fs_session_cancel(v9ses); 233322b329aSEric Van Hensbergen } 234322b329aSEric Van Hensbergen 235ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations v9fs_super_ops = { 2369e82cf6aSEric Van Hensbergen .statfs = simple_statfs, 2379e82cf6aSEric Van Hensbergen .clear_inode = v9fs_clear_inode, 2389e82cf6aSEric Van Hensbergen .show_options = v9fs_show_options, 239322b329aSEric Van Hensbergen .umount_begin = v9fs_umount_begin, 2409e82cf6aSEric Van Hensbergen }; 2419e82cf6aSEric Van Hensbergen 2429e82cf6aSEric Van Hensbergen struct file_system_type v9fs_fs_type = { 24367543e50SEric Van Hensbergen .name = "9p", 2449e82cf6aSEric Van Hensbergen .get_sb = v9fs_get_sb, 2459e82cf6aSEric Van Hensbergen .kill_sb = v9fs_kill_super, 2469e82cf6aSEric Van Hensbergen .owner = THIS_MODULE, 2479e82cf6aSEric Van Hensbergen }; 248