diff options
author | Tristan Ye <tristan.ye@oracle.com> | 2011-05-24 03:25:54 -0400 |
---|---|---|
committer | Tristan Ye <tristan.ye@oracle.com> | 2011-05-25 00:18:02 -0400 |
commit | 3e5db17d4da7f45c454940096d9e429cca12ef9f (patch) | |
tree | e808424de357b1140817341675b8624292c6c7b2 /fs/ocfs2 | |
parent | 8aa1fa360d0e2b31891f180d8b8e0f8d38f9243c (diff) |
Ocfs2: Add a new code 'OCFS2_INFO_FREEINODE' for o2info ioctl.
The new code is dedicated to calculate free inodes number of all inode_allocs,
then return the info to userpace in terms of an array.
Specially, flag 'OCFS2_INFO_FL_NON_COHERENT', manipulated by '--cluster-coherent'
from userspace, is now going to be involved. setting the flag on means no cluster
coherency considered, usually, userspace tools choose none-coherency strategy by
default for the sake of performace.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/ioctl.c | 128 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_ioctl.h | 11 |
2 files changed, 139 insertions, 0 deletions
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 373c1d153a99..4216739e163c 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include "ioctl.h" | 22 | #include "ioctl.h" |
23 | #include "resize.h" | 23 | #include "resize.h" |
24 | #include "refcounttree.h" | 24 | #include "refcounttree.h" |
25 | #include "sysfile.h" | ||
26 | #include "dir.h" | ||
27 | #include "buffer_head_io.h" | ||
25 | 28 | ||
26 | #include <linux/ext2_fs.h> | 29 | #include <linux/ext2_fs.h> |
27 | 30 | ||
@@ -52,6 +55,11 @@ static inline void o2info_clear_request_filled(struct ocfs2_info_request *req) | |||
52 | req->ir_flags &= ~OCFS2_INFO_FL_FILLED; | 55 | req->ir_flags &= ~OCFS2_INFO_FL_FILLED; |
53 | } | 56 | } |
54 | 57 | ||
58 | static inline int o2info_coherent(struct ocfs2_info_request *req) | ||
59 | { | ||
60 | return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT)); | ||
61 | } | ||
62 | |||
55 | static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) | 63 | static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) |
56 | { | 64 | { |
57 | int status; | 65 | int status; |
@@ -309,6 +317,122 @@ bail: | |||
309 | return status; | 317 | return status; |
310 | } | 318 | } |
311 | 319 | ||
320 | int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb, | ||
321 | struct inode *inode_alloc, u64 blkno, | ||
322 | struct ocfs2_info_freeinode *fi, u32 slot) | ||
323 | { | ||
324 | int status = 0, unlock = 0; | ||
325 | |||
326 | struct buffer_head *bh = NULL; | ||
327 | struct ocfs2_dinode *dinode_alloc = NULL; | ||
328 | |||
329 | if (inode_alloc) | ||
330 | mutex_lock(&inode_alloc->i_mutex); | ||
331 | |||
332 | if (o2info_coherent(&fi->ifi_req)) { | ||
333 | status = ocfs2_inode_lock(inode_alloc, &bh, 0); | ||
334 | if (status < 0) { | ||
335 | mlog_errno(status); | ||
336 | goto bail; | ||
337 | } | ||
338 | unlock = 1; | ||
339 | } else { | ||
340 | status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh); | ||
341 | if (status < 0) { | ||
342 | mlog_errno(status); | ||
343 | goto bail; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | dinode_alloc = (struct ocfs2_dinode *)bh->b_data; | ||
348 | |||
349 | fi->ifi_stat[slot].lfi_total = | ||
350 | le32_to_cpu(dinode_alloc->id1.bitmap1.i_total); | ||
351 | fi->ifi_stat[slot].lfi_free = | ||
352 | le32_to_cpu(dinode_alloc->id1.bitmap1.i_total) - | ||
353 | le32_to_cpu(dinode_alloc->id1.bitmap1.i_used); | ||
354 | |||
355 | bail: | ||
356 | if (unlock) | ||
357 | ocfs2_inode_unlock(inode_alloc, 0); | ||
358 | |||
359 | if (inode_alloc) | ||
360 | mutex_unlock(&inode_alloc->i_mutex); | ||
361 | |||
362 | brelse(bh); | ||
363 | |||
364 | return status; | ||
365 | } | ||
366 | |||
367 | int ocfs2_info_handle_freeinode(struct inode *inode, | ||
368 | struct ocfs2_info_request __user *req) | ||
369 | { | ||
370 | u32 i; | ||
371 | u64 blkno = -1; | ||
372 | char namebuf[40]; | ||
373 | int status = -EFAULT, type = INODE_ALLOC_SYSTEM_INODE; | ||
374 | struct ocfs2_info_freeinode *oifi = NULL; | ||
375 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
376 | struct inode *inode_alloc = NULL; | ||
377 | |||
378 | oifi = kzalloc(sizeof(struct ocfs2_info_freeinode), GFP_KERNEL); | ||
379 | if (!oifi) { | ||
380 | status = -ENOMEM; | ||
381 | mlog_errno(status); | ||
382 | goto bail; | ||
383 | } | ||
384 | |||
385 | if (o2info_from_user(*oifi, req)) | ||
386 | goto bail; | ||
387 | |||
388 | oifi->ifi_slotnum = osb->max_slots; | ||
389 | |||
390 | for (i = 0; i < oifi->ifi_slotnum; i++) { | ||
391 | if (o2info_coherent(&oifi->ifi_req)) { | ||
392 | inode_alloc = ocfs2_get_system_file_inode(osb, type, i); | ||
393 | if (!inode_alloc) { | ||
394 | mlog(ML_ERROR, "unable to get alloc inode in " | ||
395 | "slot %u\n", i); | ||
396 | status = -EIO; | ||
397 | goto bail; | ||
398 | } | ||
399 | } else { | ||
400 | ocfs2_sprintf_system_inode_name(namebuf, | ||
401 | sizeof(namebuf), | ||
402 | type, i); | ||
403 | status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, | ||
404 | namebuf, | ||
405 | strlen(namebuf), | ||
406 | &blkno); | ||
407 | if (status < 0) { | ||
408 | status = -ENOENT; | ||
409 | goto bail; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | status = ocfs2_info_scan_inode_alloc(osb, inode_alloc, blkno, oifi, i); | ||
414 | if (status < 0) | ||
415 | goto bail; | ||
416 | |||
417 | iput(inode_alloc); | ||
418 | inode_alloc = NULL; | ||
419 | } | ||
420 | |||
421 | o2info_set_request_filled(&oifi->ifi_req); | ||
422 | |||
423 | if (o2info_to_user(*oifi, req)) | ||
424 | goto bail; | ||
425 | |||
426 | status = 0; | ||
427 | bail: | ||
428 | if (status) | ||
429 | o2info_set_request_error(&oifi->ifi_req, req); | ||
430 | |||
431 | kfree(oifi); | ||
432 | |||
433 | return status; | ||
434 | } | ||
435 | |||
312 | int ocfs2_info_handle_unknown(struct inode *inode, | 436 | int ocfs2_info_handle_unknown(struct inode *inode, |
313 | struct ocfs2_info_request __user *req) | 437 | struct ocfs2_info_request __user *req) |
314 | { | 438 | { |
@@ -380,6 +504,10 @@ int ocfs2_info_handle_request(struct inode *inode, | |||
380 | if (oir.ir_size == sizeof(struct ocfs2_info_journal_size)) | 504 | if (oir.ir_size == sizeof(struct ocfs2_info_journal_size)) |
381 | status = ocfs2_info_handle_journal_size(inode, req); | 505 | status = ocfs2_info_handle_journal_size(inode, req); |
382 | break; | 506 | break; |
507 | case OCFS2_INFO_FREEINODE: | ||
508 | if (oir.ir_size == sizeof(struct ocfs2_info_freeinode)) | ||
509 | status = ocfs2_info_handle_freeinode(inode, req); | ||
510 | break; | ||
383 | default: | 511 | default: |
384 | status = ocfs2_info_handle_unknown(inode, req); | 512 | status = ocfs2_info_handle_unknown(inode, req); |
385 | break; | 513 | break; |
diff --git a/fs/ocfs2/ocfs2_ioctl.h b/fs/ocfs2/ocfs2_ioctl.h index b46f39bf7438..6b4b39a83662 100644 --- a/fs/ocfs2/ocfs2_ioctl.h +++ b/fs/ocfs2/ocfs2_ioctl.h | |||
@@ -142,6 +142,16 @@ struct ocfs2_info_journal_size { | |||
142 | __u64 ij_journal_size; | 142 | __u64 ij_journal_size; |
143 | }; | 143 | }; |
144 | 144 | ||
145 | struct ocfs2_info_freeinode { | ||
146 | struct ocfs2_info_request ifi_req; | ||
147 | struct ocfs2_info_local_freeinode { | ||
148 | __u64 lfi_total; | ||
149 | __u64 lfi_free; | ||
150 | } ifi_stat[OCFS2_MAX_SLOTS]; | ||
151 | __u32 ifi_slotnum; /* out */ | ||
152 | __u32 ifi_pad; | ||
153 | }; | ||
154 | |||
145 | /* Codes for ocfs2_info_request */ | 155 | /* Codes for ocfs2_info_request */ |
146 | enum ocfs2_info_type { | 156 | enum ocfs2_info_type { |
147 | OCFS2_INFO_CLUSTERSIZE = 1, | 157 | OCFS2_INFO_CLUSTERSIZE = 1, |
@@ -151,6 +161,7 @@ enum ocfs2_info_type { | |||
151 | OCFS2_INFO_UUID, | 161 | OCFS2_INFO_UUID, |
152 | OCFS2_INFO_FS_FEATURES, | 162 | OCFS2_INFO_FS_FEATURES, |
153 | OCFS2_INFO_JOURNAL_SIZE, | 163 | OCFS2_INFO_JOURNAL_SIZE, |
164 | OCFS2_INFO_FREEINODE, | ||
154 | OCFS2_INFO_NUM_TYPES | 165 | OCFS2_INFO_NUM_TYPES |
155 | }; | 166 | }; |
156 | 167 | ||