1 vfs: vfs-level fiemap interface
3 From: Eric Sandeen <sandeen@redhat.com>
5 Basic vfs-level fiemap infrastructure, which sets up a new
6 ->fiemap inode operation.
8 Signed-off-by: Eric Sandeen <sandeen@redhat.com>
11 (and I think also signed-off-by Andreas and/or Kalpak as well should
12 also go here, since it's their work originally.)
15 fs/ioctl.c | 30 ++++++++++++++++++++++++++++++
16 include/linux/fiemap.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
17 include/linux/fs.h | 3 +++
18 3 files changed, 82 insertions(+)
20 Index: linux-2.6.26-rc6/include/linux/fiemap.h
21 ===================================================================
22 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
23 +++ linux-2.6.26-rc6/include/linux/fiemap.h 2008-06-17 10:43:44.000000000 -0700
26 + * FIEMAP ioctl infrastructure.
28 + * Copyright (C) 2007 Cluster File Systems, Inc
30 + * Author: Kalpak Shah <kalpak.shah@sun.com>
31 + * Andreas Dilger <adilger@sun.com>
34 +#ifndef _LINUX_FIEMAP_H
35 +#define _LINUX_FIEMAP_H
37 +struct fiemap_extent {
38 + __u64 fe_offset; /* offset in bytes for the start of the extent */
39 + __u64 fe_length; /* length in bytes for the extent */
40 + __u32 fe_flags; /* returned FIEMAP_EXTENT_* flags for the extent */
41 + __u32 fe_lun; /* logical device number for extent (starting at 0)*/
45 + __u64 fm_start; /* logical starting byte offset (in/out) */
46 + __u64 fm_length; /* logical length of map (in/out) */
47 + __u32 fm_flags; /* FIEMAP_FLAG_* flags for request (in/out) */
48 + __u32 fm_extent_count; /* number of extents in fm_extents (in/out) */
49 + __u64 fm_end_offset; /* logical offset of end of mapping in last ioctl (out) */
50 + struct fiemap_extent fm_extents[0];
53 +#define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before map */
54 +#define FIEMAP_FLAG_HSM_READ 0x00000002 /* get data from HSM before map */
55 +#define FIEMAP_FLAG_NUM_EXTENTS 0x00000004 /* return only number of extents */
56 +#define FIEMAP_FLAG_INCOMPAT 0xff000000 /* error for unknown flags in here */
58 +#define FIEMAP_FLAG_LUN_OFFSET 0x01000000 /* use lun offsets, instead of
59 + * logical file offsets */
61 +#define FIEMAP_EXTENT_HOLE 0x00000001 /* has no data or space allocation */
62 +#define FIEMAP_EXTENT_UNWRITTEN 0x00000002 /* space allocated, but no data */
63 +#define FIEMAP_EXTENT_UNKNOWN 0x00000004 /* in use, location unknown */
64 +#define FIEMAP_EXTENT_ERROR 0x00000008 /* mapping error, errno in fe_start*/
65 +#define FIEMAP_EXTENT_NO_DIRECT 0x00000010 /* cannot access data directly */
66 +#define FIEMAP_EXTENT_LAST 0x00000020 /* last extent in the file */
67 +#define FIEMAP_EXTENT_DELALLOC 0x00000040 /* has data but not yet written,
68 + * must have EXTENT_UNKNOWN set */
69 +#define FIEMAP_EXTENT_SECONDARY 0x00000080 /* data (also) in secondary storage,
70 + * not in primary if EXTENT_UNKNOWN*/
71 +#define FIEMAP_EXTENT_EOF 0x00000100 /* if fm_start+fm_len is beyond EOF*/
73 +#endif /* _LINUX_FIEMAP_H */
74 Index: linux-2.6.26-rc6/include/linux/fs.h
75 ===================================================================
76 --- linux-2.6.26-rc6.orig/include/linux/fs.h 2008-06-17 10:43:35.000000000 -0700
77 +++ linux-2.6.26-rc6/include/linux/fs.h 2008-06-17 10:43:44.000000000 -0700
78 @@ -228,6 +228,7 @@ extern int dir_notify_enable;
79 #define FS_IOC_SETFLAGS _IOW('f', 2, long)
80 #define FS_IOC_GETVERSION _IOR('v', 1, long)
81 #define FS_IOC_SETVERSION _IOW('v', 2, long)
82 +#define FS_IOC_FIEMAP _IOWR('f', 10, struct fiemap)
83 #define FS_IOC32_GETFLAGS _IOR('f', 1, int)
84 #define FS_IOC32_SETFLAGS _IOW('f', 2, int)
85 #define FS_IOC32_GETVERSION _IOR('v', 1, int)
86 @@ -288,6 +289,7 @@ extern int dir_notify_enable;
87 #include <linux/mutex.h>
88 #include <linux/capability.h>
89 #include <linux/semaphore.h>
90 +#include <linux/fiemap.h>
92 #include <asm/atomic.h>
93 #include <asm/byteorder.h>
94 @@ -1273,6 +1275,7 @@ struct inode_operations {
95 void (*truncate_range)(struct inode *, loff_t, loff_t);
96 long (*fallocate)(struct inode *inode, int mode, loff_t offset,
98 + int (*fiemap) (struct inode *, unsigned long arg);
102 Index: linux-2.6.26-rc6/fs/ioctl.c
103 ===================================================================
104 --- linux-2.6.26-rc6.orig/fs/ioctl.c 2008-06-17 10:21:23.000000000 -0700
105 +++ linux-2.6.26-rc6/fs/ioctl.c 2008-06-17 10:43:44.000000000 -0700
106 @@ -71,6 +71,34 @@ static int ioctl_fibmap(struct file *fil
107 return put_user(res, p);
110 +static int ioctl_fiemap(struct file *filp, unsigned long arg)
112 + struct fiemap fiemap_s;
113 + struct inode *inode = filp->f_path.dentry->d_inode;
116 + if (!inode->i_op->fiemap)
117 + return -EOPNOTSUPP;
119 + if (copy_from_user(&fiemap_s, (struct fiemap __user *)arg,
120 + sizeof(struct fiemap)))
123 + /* Need arg sanity checking:
124 + * start >= 0? Must be; unsigned.
125 + * length > 0? (or is -1 valid?)
126 + * extent count non-zero if not FLAG_NUM_EXTENTS
129 + /* Should fs do this under a lock? */
130 + if (fiemap_s.fm_flags & FIEMAP_FLAG_SYNC)
131 + filemap_write_and_wait(inode->i_mapping);
133 + error = inode->i_op->fiemap(inode, arg);
138 static int file_ioctl(struct file *filp, unsigned int cmd,
141 @@ -80,6 +108,8 @@ static int file_ioctl(struct file *filp,
144 return ioctl_fibmap(filp, p);
145 + case FS_IOC_FIEMAP:
146 + return ioctl_fiemap(filp, arg);
148 return put_user(inode->i_sb->s_blocksize, p);