diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 107 |
1 files changed, 45 insertions, 62 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 4bd112313f33..d0b499418a7d 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
35 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_ioctl.h" | ||
37 | #include "xfs_btree.h" | 38 | #include "xfs_btree.h" |
38 | #include "xfs_ialloc.h" | 39 | #include "xfs_ialloc.h" |
39 | #include "xfs_rtalloc.h" | 40 | #include "xfs_rtalloc.h" |
@@ -78,92 +79,74 @@ xfs_find_handle( | |||
78 | int hsize; | 79 | int hsize; |
79 | xfs_handle_t handle; | 80 | xfs_handle_t handle; |
80 | struct inode *inode; | 81 | struct inode *inode; |
82 | struct file *file = NULL; | ||
83 | struct path path; | ||
84 | int error; | ||
85 | struct xfs_inode *ip; | ||
81 | 86 | ||
82 | memset((char *)&handle, 0, sizeof(handle)); | 87 | if (cmd == XFS_IOC_FD_TO_HANDLE) { |
83 | 88 | file = fget(hreq->fd); | |
84 | switch (cmd) { | 89 | if (!file) |
85 | case XFS_IOC_PATH_TO_FSHANDLE: | 90 | return -EBADF; |
86 | case XFS_IOC_PATH_TO_HANDLE: { | 91 | inode = file->f_path.dentry->d_inode; |
87 | struct path path; | 92 | } else { |
88 | int error = user_lpath((const char __user *)hreq->path, &path); | 93 | error = user_lpath((const char __user *)hreq->path, &path); |
89 | if (error) | 94 | if (error) |
90 | return error; | 95 | return error; |
91 | 96 | inode = path.dentry->d_inode; | |
92 | ASSERT(path.dentry); | ||
93 | ASSERT(path.dentry->d_inode); | ||
94 | inode = igrab(path.dentry->d_inode); | ||
95 | path_put(&path); | ||
96 | break; | ||
97 | } | 97 | } |
98 | ip = XFS_I(inode); | ||
98 | 99 | ||
99 | case XFS_IOC_FD_TO_HANDLE: { | 100 | /* |
100 | struct file *file; | 101 | * We can only generate handles for inodes residing on a XFS filesystem, |
101 | 102 | * and only for regular files, directories or symbolic links. | |
102 | file = fget(hreq->fd); | 103 | */ |
103 | if (!file) | 104 | error = -EINVAL; |
104 | return -EBADF; | 105 | if (inode->i_sb->s_magic != XFS_SB_MAGIC) |
106 | goto out_put; | ||
105 | 107 | ||
106 | ASSERT(file->f_path.dentry); | 108 | error = -EBADF; |
107 | ASSERT(file->f_path.dentry->d_inode); | 109 | if (!S_ISREG(inode->i_mode) && |
108 | inode = igrab(file->f_path.dentry->d_inode); | 110 | !S_ISDIR(inode->i_mode) && |
109 | fput(file); | 111 | !S_ISLNK(inode->i_mode)) |
110 | break; | 112 | goto out_put; |
111 | } | ||
112 | 113 | ||
113 | default: | ||
114 | ASSERT(0); | ||
115 | return -XFS_ERROR(EINVAL); | ||
116 | } | ||
117 | 114 | ||
118 | if (inode->i_sb->s_magic != XFS_SB_MAGIC) { | 115 | memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t)); |
119 | /* we're not in XFS anymore, Toto */ | ||
120 | iput(inode); | ||
121 | return -XFS_ERROR(EINVAL); | ||
122 | } | ||
123 | 116 | ||
124 | switch (inode->i_mode & S_IFMT) { | 117 | if (cmd == XFS_IOC_PATH_TO_FSHANDLE) { |
125 | case S_IFREG: | 118 | /* |
126 | case S_IFDIR: | 119 | * This handle only contains an fsid, zero the rest. |
127 | case S_IFLNK: | 120 | */ |
128 | break; | 121 | memset(&handle.ha_fid, 0, sizeof(handle.ha_fid)); |
129 | default: | 122 | hsize = sizeof(xfs_fsid_t); |
130 | iput(inode); | 123 | } else { |
131 | return -XFS_ERROR(EBADF); | ||
132 | } | ||
133 | |||
134 | /* now we can grab the fsid */ | ||
135 | memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid, | ||
136 | sizeof(xfs_fsid_t)); | ||
137 | hsize = sizeof(xfs_fsid_t); | ||
138 | |||
139 | if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { | ||
140 | xfs_inode_t *ip = XFS_I(inode); | ||
141 | int lock_mode; | 124 | int lock_mode; |
142 | 125 | ||
143 | /* need to get access to the xfs_inode to read the generation */ | ||
144 | lock_mode = xfs_ilock_map_shared(ip); | 126 | lock_mode = xfs_ilock_map_shared(ip); |
145 | |||
146 | /* fill in fid section of handle from inode */ | ||
147 | handle.ha_fid.fid_len = sizeof(xfs_fid_t) - | 127 | handle.ha_fid.fid_len = sizeof(xfs_fid_t) - |
148 | sizeof(handle.ha_fid.fid_len); | 128 | sizeof(handle.ha_fid.fid_len); |
149 | handle.ha_fid.fid_pad = 0; | 129 | handle.ha_fid.fid_pad = 0; |
150 | handle.ha_fid.fid_gen = ip->i_d.di_gen; | 130 | handle.ha_fid.fid_gen = ip->i_d.di_gen; |
151 | handle.ha_fid.fid_ino = ip->i_ino; | 131 | handle.ha_fid.fid_ino = ip->i_ino; |
152 | |||
153 | xfs_iunlock_map_shared(ip, lock_mode); | 132 | xfs_iunlock_map_shared(ip, lock_mode); |
154 | 133 | ||
155 | hsize = XFS_HSIZE(handle); | 134 | hsize = XFS_HSIZE(handle); |
156 | } | 135 | } |
157 | 136 | ||
158 | /* now copy our handle into the user buffer & write out the size */ | 137 | error = -EFAULT; |
159 | if (copy_to_user(hreq->ohandle, &handle, hsize) || | 138 | if (copy_to_user(hreq->ohandle, &handle, hsize) || |
160 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) { | 139 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) |
161 | iput(inode); | 140 | goto out_put; |
162 | return -XFS_ERROR(EFAULT); | ||
163 | } | ||
164 | 141 | ||
165 | iput(inode); | 142 | error = 0; |
166 | return 0; | 143 | |
144 | out_put: | ||
145 | if (cmd == XFS_IOC_FD_TO_HANDLE) | ||
146 | fput(file); | ||
147 | else | ||
148 | path_put(&path); | ||
149 | return error; | ||
167 | } | 150 | } |
168 | 151 | ||
169 | /* | 152 | /* |