1 /* 2 * linux/fs/9p/vfs_dir.c 3 * 4 * This file contains vfs directory ops for the 9P2000 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/stat.h> 31 #include <linux/string.h> 32 #include <linux/sched.h> 33 #include <linux/inet.h> 34 #include <linux/idr.h> 35 #include <net/9p/9p.h> 36 #include <net/9p/client.h> 37 38 #include "v9fs.h" 39 #include "v9fs_vfs.h" 40 #include "fid.h" 41 42 /** 43 * dt_type - return file type 44 * @mistat: mistat structure 45 * 46 */ 47 48 static inline int dt_type(struct p9_stat *mistat) 49 { 50 unsigned long perm = mistat->mode; 51 int rettype = DT_REG; 52 53 if (perm & P9_DMDIR) 54 rettype = DT_DIR; 55 if (perm & P9_DMSYMLINK) 56 rettype = DT_LNK; 57 58 return rettype; 59 } 60 61 /** 62 * v9fs_dir_readdir - read a directory 63 * @filp: opened file structure 64 * @dirent: directory structure ??? 65 * @filldir: function to populate directory structure ??? 66 * 67 */ 68 69 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 70 { 71 int over; 72 struct p9_fid *fid; 73 struct v9fs_session_info *v9ses; 74 struct inode *inode; 75 struct p9_stat *st; 76 77 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 78 inode = filp->f_path.dentry->d_inode; 79 v9ses = v9fs_inode2v9ses(inode); 80 fid = filp->private_data; 81 while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) { 82 if (IS_ERR(st)) 83 return PTR_ERR(st); 84 85 over = filldir(dirent, st->name.str, st->name.len, filp->f_pos, 86 v9fs_qid2ino(&st->qid), dt_type(st)); 87 88 if (over) 89 break; 90 91 filp->f_pos += st->size; 92 kfree(st); 93 st = NULL; 94 } 95 96 kfree(st); 97 return 0; 98 } 99 100 101 /** 102 * v9fs_dir_release - close a directory 103 * @inode: inode of the directory 104 * @filp: file pointer to a directory 105 * 106 */ 107 108 int v9fs_dir_release(struct inode *inode, struct file *filp) 109 { 110 struct p9_fid *fid; 111 112 fid = filp->private_data; 113 P9_DPRINTK(P9_DEBUG_VFS, 114 "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); 115 filemap_write_and_wait(inode->i_mapping); 116 p9_client_clunk(fid); 117 return 0; 118 } 119 120 const struct file_operations v9fs_dir_operations = { 121 .read = generic_read_dir, 122 .readdir = v9fs_dir_readdir, 123 .open = v9fs_file_open, 124 .release = v9fs_dir_release, 125 }; 126