aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/ioctl.c
diff options
context:
space:
mode:
authorTristan Ye <tristan.ye@oracle.com>2011-05-24 03:25:54 -0400
committerTristan Ye <tristan.ye@oracle.com>2011-05-25 00:18:02 -0400
commit3e5db17d4da7f45c454940096d9e429cca12ef9f (patch)
treee808424de357b1140817341675b8624292c6c7b2 /fs/ocfs2/ioctl.c
parent8aa1fa360d0e2b31891f180d8b8e0f8d38f9243c (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/ioctl.c')
-rw-r--r--fs/ocfs2/ioctl.c128
1 files changed, 128 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
58static inline int o2info_coherent(struct ocfs2_info_request *req)
59{
60 return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));
61}
62
55static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) 63static 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
320int 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
355bail:
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
367int 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;
427bail:
428 if (status)
429 o2info_set_request_error(&oifi->ifi_req, req);
430
431 kfree(oifi);
432
433 return status;
434}
435
312int ocfs2_info_handle_unknown(struct inode *inode, 436int 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;