aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-05-08 03:26:17 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:03 -0400
commit2793274298c4423d79701e9a8190f2940bf3c785 (patch)
tree8cc0cf9889f3426b9ca50d3cfa15e775ad31d2d8 /fs
parentc5141e6d64ab5c48a5e31413c7a6cdda84ac1d52 (diff)
add file position info to proc
Add support for finding out the current file position, open flags and possibly other info in the future. These new entries are added: /proc/PID/fdinfo/FD /proc/PID/task/TID/fdinfo/FD For each fd the information is provided in the following format: pos: 1234 flags: 0100002 [bunk@stusta.de: make struct proc_fdinfo_file_operations static] Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Cc: Alexey Dobriyan <adobriyan@sw.ru> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/proc/base.c132
1 files changed, 114 insertions, 18 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index be94ddebb413..0697fd089de8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1238,7 +1238,10 @@ out:
1238 return ~0U; 1238 return ~0U;
1239} 1239}
1240 1240
1241static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) 1241#define PROC_FDINFO_MAX 64
1242
1243static int proc_fd_info(struct inode *inode, struct dentry **dentry,
1244 struct vfsmount **mnt, char *info)
1242{ 1245{
1243 struct task_struct *task = get_proc_task(inode); 1246 struct task_struct *task = get_proc_task(inode);
1244 struct files_struct *files = NULL; 1247 struct files_struct *files = NULL;
@@ -1257,8 +1260,16 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
1257 spin_lock(&files->file_lock); 1260 spin_lock(&files->file_lock);
1258 file = fcheck_files(files, fd); 1261 file = fcheck_files(files, fd);
1259 if (file) { 1262 if (file) {
1260 *mnt = mntget(file->f_path.mnt); 1263 if (mnt)
1261 *dentry = dget(file->f_path.dentry); 1264 *mnt = mntget(file->f_path.mnt);
1265 if (dentry)
1266 *dentry = dget(file->f_path.dentry);
1267 if (info)
1268 snprintf(info, PROC_FDINFO_MAX,
1269 "pos:\t%lli\n"
1270 "flags:\t0%o\n",
1271 (long long) file->f_pos,
1272 file->f_flags);
1262 spin_unlock(&files->file_lock); 1273 spin_unlock(&files->file_lock);
1263 put_files_struct(files); 1274 put_files_struct(files);
1264 return 0; 1275 return 0;
@@ -1269,6 +1280,12 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
1269 return -ENOENT; 1280 return -ENOENT;
1270} 1281}
1271 1282
1283static int proc_fd_link(struct inode *inode, struct dentry **dentry,
1284 struct vfsmount **mnt)
1285{
1286 return proc_fd_info(inode, dentry, mnt, NULL);
1287}
1288
1272static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) 1289static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1273{ 1290{
1274 struct inode *inode = dentry->d_inode; 1291 struct inode *inode = dentry->d_inode;
@@ -1364,7 +1381,9 @@ out_iput:
1364 goto out; 1381 goto out;
1365} 1382}
1366 1383
1367static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd) 1384static struct dentry *proc_lookupfd_common(struct inode *dir,
1385 struct dentry *dentry,
1386 instantiate_t instantiate)
1368{ 1387{
1369 struct task_struct *task = get_proc_task(dir); 1388 struct task_struct *task = get_proc_task(dir);
1370 unsigned fd = name_to_int(dentry); 1389 unsigned fd = name_to_int(dentry);
@@ -1375,23 +1394,15 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1375 if (fd == ~0U) 1394 if (fd == ~0U)
1376 goto out; 1395 goto out;
1377 1396
1378 result = proc_fd_instantiate(dir, dentry, task, &fd); 1397 result = instantiate(dir, dentry, task, &fd);
1379out: 1398out:
1380 put_task_struct(task); 1399 put_task_struct(task);
1381out_no_task: 1400out_no_task:
1382 return result; 1401 return result;
1383} 1402}
1384 1403
1385static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir, 1404static int proc_readfd_common(struct file * filp, void * dirent,
1386 struct task_struct *task, int fd) 1405 filldir_t filldir, instantiate_t instantiate)
1387{
1388 char name[PROC_NUMBUF];
1389 int len = snprintf(name, sizeof(name), "%d", fd);
1390 return proc_fill_cache(filp, dirent, filldir, name, len,
1391 proc_fd_instantiate, task, &fd);
1392}
1393
1394static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1395{ 1406{
1396 struct dentry *dentry = filp->f_path.dentry; 1407 struct dentry *dentry = filp->f_path.dentry;
1397 struct inode *inode = dentry->d_inode; 1408 struct inode *inode = dentry->d_inode;
@@ -1427,12 +1438,17 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1427 for (fd = filp->f_pos-2; 1438 for (fd = filp->f_pos-2;
1428 fd < fdt->max_fds; 1439 fd < fdt->max_fds;
1429 fd++, filp->f_pos++) { 1440 fd++, filp->f_pos++) {
1441 char name[PROC_NUMBUF];
1442 int len;
1430 1443
1431 if (!fcheck_files(files, fd)) 1444 if (!fcheck_files(files, fd))
1432 continue; 1445 continue;
1433 rcu_read_unlock(); 1446 rcu_read_unlock();
1434 1447
1435 if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) { 1448 len = snprintf(name, sizeof(name), "%d", fd);
1449 if (proc_fill_cache(filp, dirent, filldir,
1450 name, len, instantiate,
1451 p, &fd) < 0) {
1436 rcu_read_lock(); 1452 rcu_read_lock();
1437 break; 1453 break;
1438 } 1454 }
@@ -1447,6 +1463,32 @@ out_no_task:
1447 return retval; 1463 return retval;
1448} 1464}
1449 1465
1466static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
1467 struct nameidata *nd)
1468{
1469 return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
1470}
1471
1472static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
1473{
1474 return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
1475}
1476
1477static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
1478 size_t len, loff_t *ppos)
1479{
1480 char tmp[PROC_FDINFO_MAX];
1481 int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, NULL, tmp);
1482 if (!err)
1483 err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
1484 return err;
1485}
1486
1487static const struct file_operations proc_fdinfo_file_operations = {
1488 .open = nonseekable_open,
1489 .read = proc_fdinfo_read,
1490};
1491
1450static const struct file_operations proc_fd_operations = { 1492static const struct file_operations proc_fd_operations = {
1451 .read = generic_read_dir, 1493 .read = generic_read_dir,
1452 .readdir = proc_readfd, 1494 .readdir = proc_readfd,
@@ -1478,6 +1520,58 @@ static const struct inode_operations proc_fd_inode_operations = {
1478 .setattr = proc_setattr, 1520 .setattr = proc_setattr,
1479}; 1521};
1480 1522
1523static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
1524 struct dentry *dentry, struct task_struct *task, const void *ptr)
1525{
1526 unsigned fd = *(unsigned *)ptr;
1527 struct inode *inode;
1528 struct proc_inode *ei;
1529 struct dentry *error = ERR_PTR(-ENOENT);
1530
1531 inode = proc_pid_make_inode(dir->i_sb, task);
1532 if (!inode)
1533 goto out;
1534 ei = PROC_I(inode);
1535 ei->fd = fd;
1536 inode->i_mode = S_IFREG | S_IRUSR;
1537 inode->i_fop = &proc_fdinfo_file_operations;
1538 dentry->d_op = &tid_fd_dentry_operations;
1539 d_add(dentry, inode);
1540 /* Close the race of the process dying before we return the dentry */
1541 if (tid_fd_revalidate(dentry, NULL))
1542 error = NULL;
1543
1544 out:
1545 return error;
1546}
1547
1548static struct dentry *proc_lookupfdinfo(struct inode *dir,
1549 struct dentry *dentry,
1550 struct nameidata *nd)
1551{
1552 return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
1553}
1554
1555static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
1556{
1557 return proc_readfd_common(filp, dirent, filldir,
1558 proc_fdinfo_instantiate);
1559}
1560
1561static const struct file_operations proc_fdinfo_operations = {
1562 .read = generic_read_dir,
1563 .readdir = proc_readfdinfo,
1564};
1565
1566/*
1567 * proc directories can do almost nothing..
1568 */
1569static const struct inode_operations proc_fdinfo_inode_operations = {
1570 .lookup = proc_lookupfdinfo,
1571 .setattr = proc_setattr,
1572};
1573
1574
1481static struct dentry *proc_pident_instantiate(struct inode *dir, 1575static struct dentry *proc_pident_instantiate(struct inode *dir,
1482 struct dentry *dentry, struct task_struct *task, const void *ptr) 1576 struct dentry *dentry, struct task_struct *task, const void *ptr)
1483{ 1577{
@@ -1888,6 +1982,7 @@ static const struct inode_operations proc_task_inode_operations;
1888static const struct pid_entry tgid_base_stuff[] = { 1982static const struct pid_entry tgid_base_stuff[] = {
1889 DIR("task", S_IRUGO|S_IXUGO, task), 1983 DIR("task", S_IRUGO|S_IXUGO, task),
1890 DIR("fd", S_IRUSR|S_IXUSR, fd), 1984 DIR("fd", S_IRUSR|S_IXUSR, fd),
1985 DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo),
1891 INF("environ", S_IRUSR, pid_environ), 1986 INF("environ", S_IRUSR, pid_environ),
1892 INF("auxv", S_IRUSR, pid_auxv), 1987 INF("auxv", S_IRUSR, pid_auxv),
1893 INF("status", S_IRUGO, pid_status), 1988 INF("status", S_IRUGO, pid_status),
@@ -2041,7 +2136,7 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
2041 inode->i_op = &proc_tgid_base_inode_operations; 2136 inode->i_op = &proc_tgid_base_inode_operations;
2042 inode->i_fop = &proc_tgid_base_operations; 2137 inode->i_fop = &proc_tgid_base_operations;
2043 inode->i_flags|=S_IMMUTABLE; 2138 inode->i_flags|=S_IMMUTABLE;
2044 inode->i_nlink = 4; 2139 inode->i_nlink = 5;
2045#ifdef CONFIG_SECURITY 2140#ifdef CONFIG_SECURITY
2046 inode->i_nlink += 1; 2141 inode->i_nlink += 1;
2047#endif 2142#endif
@@ -2171,6 +2266,7 @@ out_no_task:
2171 */ 2266 */
2172static const struct pid_entry tid_base_stuff[] = { 2267static const struct pid_entry tid_base_stuff[] = {
2173 DIR("fd", S_IRUSR|S_IXUSR, fd), 2268 DIR("fd", S_IRUSR|S_IXUSR, fd),
2269 DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo),
2174 INF("environ", S_IRUSR, pid_environ), 2270 INF("environ", S_IRUSR, pid_environ),
2175 INF("auxv", S_IRUSR, pid_auxv), 2271 INF("auxv", S_IRUSR, pid_auxv),
2176 INF("status", S_IRUGO, pid_status), 2272 INF("status", S_IRUGO, pid_status),
@@ -2251,7 +2347,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
2251 inode->i_op = &proc_tid_base_inode_operations; 2347 inode->i_op = &proc_tid_base_inode_operations;
2252 inode->i_fop = &proc_tid_base_operations; 2348 inode->i_fop = &proc_tid_base_operations;
2253 inode->i_flags|=S_IMMUTABLE; 2349 inode->i_flags|=S_IMMUTABLE;
2254 inode->i_nlink = 3; 2350 inode->i_nlink = 4;
2255#ifdef CONFIG_SECURITY 2351#ifdef CONFIG_SECURITY
2256 inode->i_nlink += 1; 2352 inode->i_nlink += 1;
2257#endif 2353#endif