diff options
| -rw-r--r-- | fs/gfs2/ops_file.c | 187 |
1 files changed, 9 insertions, 178 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 80f3ff0bba7b..372dbcb3f7f3 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
| @@ -43,27 +43,6 @@ | |||
| 43 | #include "util.h" | 43 | #include "util.h" |
| 44 | #include "eaops.h" | 44 | #include "eaops.h" |
| 45 | 45 | ||
| 46 | /* "bad" is for NFS support */ | ||
| 47 | struct filldir_bad_entry { | ||
| 48 | char *fbe_name; | ||
| 49 | unsigned int fbe_length; | ||
| 50 | u64 fbe_offset; | ||
| 51 | struct gfs2_inum fbe_inum; | ||
| 52 | unsigned int fbe_type; | ||
| 53 | }; | ||
| 54 | |||
| 55 | struct filldir_bad { | ||
| 56 | struct gfs2_sbd *fdb_sbd; | ||
| 57 | |||
| 58 | struct filldir_bad_entry *fdb_entry; | ||
| 59 | unsigned int fdb_entry_num; | ||
| 60 | unsigned int fdb_entry_off; | ||
| 61 | |||
| 62 | char *fdb_name; | ||
| 63 | unsigned int fdb_name_size; | ||
| 64 | unsigned int fdb_name_off; | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* For regular, non-NFS */ | 46 | /* For regular, non-NFS */ |
| 68 | struct filldir_reg { | 47 | struct filldir_reg { |
| 69 | struct gfs2_sbd *fdr_sbd; | 48 | struct gfs2_sbd *fdr_sbd; |
| @@ -149,7 +128,7 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) | |||
| 149 | } | 128 | } |
| 150 | 129 | ||
| 151 | /** | 130 | /** |
| 152 | * filldir_reg_func - Report a directory entry to the caller of gfs2_dir_read() | 131 | * filldir_func - Report a directory entry to the caller of gfs2_dir_read() |
| 153 | * @opaque: opaque data used by the function | 132 | * @opaque: opaque data used by the function |
| 154 | * @name: the name of the directory entry | 133 | * @name: the name of the directory entry |
| 155 | * @length: the length of the name | 134 | * @length: the length of the name |
| @@ -160,9 +139,9 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) | |||
| 160 | * Returns: 0 on success, 1 if buffer full | 139 | * Returns: 0 on success, 1 if buffer full |
| 161 | */ | 140 | */ |
| 162 | 141 | ||
| 163 | static int filldir_reg_func(void *opaque, const char *name, unsigned int length, | 142 | static int filldir_func(void *opaque, const char *name, unsigned int length, |
| 164 | u64 offset, struct gfs2_inum *inum, | 143 | u64 offset, struct gfs2_inum *inum, |
| 165 | unsigned int type) | 144 | unsigned int type) |
| 166 | { | 145 | { |
| 167 | struct filldir_reg *fdr = (struct filldir_reg *)opaque; | 146 | struct filldir_reg *fdr = (struct filldir_reg *)opaque; |
| 168 | struct gfs2_sbd *sdp = fdr->fdr_sbd; | 147 | struct gfs2_sbd *sdp = fdr->fdr_sbd; |
| @@ -174,11 +153,9 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, | |||
| 174 | return 1; | 153 | return 1; |
| 175 | 154 | ||
| 176 | if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) { | 155 | if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) { |
| 177 | gfs2_glock_prefetch_num(sdp, | 156 | gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_inode_glops, |
| 178 | inum->no_addr, &gfs2_inode_glops, | ||
| 179 | LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); | 157 | LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); |
| 180 | gfs2_glock_prefetch_num(sdp, | 158 | gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_iopen_glops, |
| 181 | inum->no_addr, &gfs2_iopen_glops, | ||
| 182 | LM_ST_SHARED, LM_FLAG_TRY); | 159 | LM_ST_SHARED, LM_FLAG_TRY); |
| 183 | } | 160 | } |
| 184 | 161 | ||
| @@ -186,7 +163,7 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, | |||
| 186 | } | 163 | } |
| 187 | 164 | ||
| 188 | /** | 165 | /** |
| 189 | * readdir_reg - Read directory entries from a directory | 166 | * gfs2_readdir - Read directory entries from a directory |
| 190 | * @file: The directory to read from | 167 | * @file: The directory to read from |
| 191 | * @dirent: Buffer for dirents | 168 | * @dirent: Buffer for dirents |
| 192 | * @filldir: Function used to do the copying | 169 | * @filldir: Function used to do the copying |
| @@ -194,7 +171,7 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, | |||
| 194 | * Returns: errno | 171 | * Returns: errno |
| 195 | */ | 172 | */ |
| 196 | 173 | ||
| 197 | static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) | 174 | static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) |
| 198 | { | 175 | { |
| 199 | struct inode *dir = file->f_mapping->host; | 176 | struct inode *dir = file->f_mapping->host; |
| 200 | struct gfs2_inode *dip = GFS2_I(dir); | 177 | struct gfs2_inode *dip = GFS2_I(dir); |
| @@ -215,7 +192,7 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) | |||
| 215 | return error; | 192 | return error; |
| 216 | } | 193 | } |
| 217 | 194 | ||
| 218 | error = gfs2_dir_read(dir, &offset, &fdr, filldir_reg_func); | 195 | error = gfs2_dir_read(dir, &offset, &fdr, filldir_func); |
| 219 | 196 | ||
| 220 | gfs2_glock_dq_uninit(&d_gh); | 197 | gfs2_glock_dq_uninit(&d_gh); |
| 221 | 198 | ||
| @@ -224,152 +201,6 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) | |||
| 224 | return error; | 201 | return error; |
| 225 | } | 202 | } |
| 226 | 203 | ||
| 227 | /** | ||
| 228 | * filldir_bad_func - Report a directory entry to the caller of gfs2_dir_read() | ||
| 229 | * @opaque: opaque data used by the function | ||
| 230 | * @name: the name of the directory entry | ||
| 231 | * @length: the length of the name | ||
| 232 | * @offset: the entry's offset in the directory | ||
| 233 | * @inum: the inode number the entry points to | ||
| 234 | * @type: the type of inode the entry points to | ||
| 235 | * | ||
| 236 | * For supporting NFS. | ||
| 237 | * | ||
| 238 | * Returns: 0 on success, 1 if buffer full | ||
| 239 | */ | ||
| 240 | |||
| 241 | static int filldir_bad_func(void *opaque, const char *name, unsigned int length, | ||
| 242 | u64 offset, struct gfs2_inum *inum, | ||
| 243 | unsigned int type) | ||
| 244 | { | ||
| 245 | struct filldir_bad *fdb = (struct filldir_bad *)opaque; | ||
| 246 | struct gfs2_sbd *sdp = fdb->fdb_sbd; | ||
| 247 | struct filldir_bad_entry *fbe; | ||
| 248 | |||
| 249 | if (fdb->fdb_entry_off == fdb->fdb_entry_num || | ||
| 250 | fdb->fdb_name_off + length > fdb->fdb_name_size) | ||
| 251 | return 1; | ||
| 252 | |||
| 253 | fbe = &fdb->fdb_entry[fdb->fdb_entry_off]; | ||
| 254 | fbe->fbe_name = fdb->fdb_name + fdb->fdb_name_off; | ||
| 255 | memcpy(fbe->fbe_name, name, length); | ||
| 256 | fbe->fbe_length = length; | ||
| 257 | fbe->fbe_offset = offset; | ||
| 258 | fbe->fbe_inum = *inum; | ||
| 259 | fbe->fbe_type = type; | ||
| 260 | |||
| 261 | fdb->fdb_entry_off++; | ||
| 262 | fdb->fdb_name_off += length; | ||
| 263 | |||
| 264 | if (!(length == 1 && *name == '.')) { | ||
| 265 | gfs2_glock_prefetch_num(sdp, | ||
| 266 | inum->no_addr, &gfs2_inode_glops, | ||
| 267 | LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); | ||
| 268 | gfs2_glock_prefetch_num(sdp, | ||
| 269 | inum->no_addr, &gfs2_iopen_glops, | ||
| 270 | LM_ST_SHARED, LM_FLAG_TRY); | ||
| 271 | } | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * readdir_bad - Read directory entries from a directory | ||
| 278 | * @file: The directory to read from | ||
| 279 | * @dirent: Buffer for dirents | ||
| 280 | * @filldir: Function used to do the copying | ||
| 281 | * | ||
| 282 | * For supporting NFS. | ||
| 283 | * | ||
| 284 | * Returns: errno | ||
| 285 | */ | ||
| 286 | |||
| 287 | static int readdir_bad(struct file *file, void *dirent, filldir_t filldir) | ||
| 288 | { | ||
| 289 | struct inode *dir = file->f_mapping->host; | ||
| 290 | struct gfs2_inode *dip = GFS2_I(dir); | ||
| 291 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
| 292 | struct filldir_reg fdr; | ||
| 293 | unsigned int entries, size; | ||
| 294 | struct filldir_bad *fdb; | ||
| 295 | struct gfs2_holder d_gh; | ||
| 296 | u64 offset = file->f_pos; | ||
| 297 | unsigned int x; | ||
| 298 | struct filldir_bad_entry *fbe; | ||
| 299 | int error; | ||
| 300 | |||
| 301 | entries = gfs2_tune_get(sdp, gt_entries_per_readdir); | ||
| 302 | size = sizeof(struct filldir_bad) + | ||
| 303 | entries * (sizeof(struct filldir_bad_entry) + GFS2_FAST_NAME_SIZE); | ||
| 304 | |||
| 305 | fdb = kzalloc(size, GFP_KERNEL); | ||
| 306 | if (!fdb) | ||
| 307 | return -ENOMEM; | ||
| 308 | |||
| 309 | fdb->fdb_sbd = sdp; | ||
| 310 | fdb->fdb_entry = (struct filldir_bad_entry *)(fdb + 1); | ||
| 311 | fdb->fdb_entry_num = entries; | ||
| 312 | fdb->fdb_name = ((char *)fdb) + sizeof(struct filldir_bad) + | ||
| 313 | entries * sizeof(struct filldir_bad_entry); | ||
| 314 | fdb->fdb_name_size = entries * GFS2_FAST_NAME_SIZE; | ||
| 315 | |||
| 316 | gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); | ||
| 317 | error = gfs2_glock_nq_atime(&d_gh); | ||
| 318 | if (error) { | ||
| 319 | gfs2_holder_uninit(&d_gh); | ||
| 320 | goto out; | ||
| 321 | } | ||
| 322 | |||
| 323 | error = gfs2_dir_read(dir, &offset, fdb, filldir_bad_func); | ||
| 324 | |||
| 325 | gfs2_glock_dq_uninit(&d_gh); | ||
| 326 | |||
| 327 | fdr.fdr_sbd = sdp; | ||
| 328 | fdr.fdr_prefetch = 0; | ||
| 329 | fdr.fdr_filldir = filldir; | ||
| 330 | fdr.fdr_opaque = dirent; | ||
| 331 | |||
| 332 | for (x = 0; x < fdb->fdb_entry_off; x++) { | ||
| 333 | fbe = &fdb->fdb_entry[x]; | ||
| 334 | |||
| 335 | error = filldir_reg_func(&fdr, | ||
| 336 | fbe->fbe_name, fbe->fbe_length, | ||
| 337 | fbe->fbe_offset, | ||
| 338 | &fbe->fbe_inum, fbe->fbe_type); | ||
| 339 | if (error) { | ||
| 340 | file->f_pos = fbe->fbe_offset; | ||
| 341 | error = 0; | ||
| 342 | goto out; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | file->f_pos = offset; | ||
| 347 | |||
| 348 | out: | ||
| 349 | kfree(fdb); | ||
| 350 | return error; | ||
| 351 | } | ||
| 352 | |||
| 353 | /** | ||
| 354 | * gfs2_readdir - Read directory entries from a directory | ||
| 355 | * @file: The directory to read from | ||
| 356 | * @dirent: Buffer for dirents | ||
| 357 | * @filldir: Function used to do the copying | ||
| 358 | * | ||
| 359 | * Returns: errno | ||
| 360 | */ | ||
| 361 | |||
| 362 | static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
| 363 | { | ||
| 364 | int error; | ||
| 365 | |||
| 366 | if (strcmp(current->comm, "nfsd") != 0) | ||
| 367 | error = readdir_reg(file, dirent, filldir); | ||
| 368 | else | ||
| 369 | error = readdir_bad(file, dirent, filldir); | ||
| 370 | |||
| 371 | return error; | ||
| 372 | } | ||
| 373 | 204 | ||
| 374 | static const u32 iflags_to_gfs2[32] = { | 205 | static const u32 iflags_to_gfs2[32] = { |
| 375 | [iflag_Sync] = GFS2_DIF_SYNC, | 206 | [iflag_Sync] = GFS2_DIF_SYNC, |
