aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:49 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:26 -0500
commitfa0d7e3de6d6fc5004ad9dea0dd6b286af8f03e9 (patch)
tree203e0f73883e4c26b5597e36042386a1237dab35 /fs/ufs
parent77812a1ef139d84270d27faacc0630c887411013 (diff)
fs: icache RCU free inodes
RCU free the struct inode. This will allow: - Subsequent store-free path walking patch. The inode must be consulted for permissions when walking, so an RCU inode reference is a must. - sb_inode_list_lock to be moved inside i_lock because sb list walkers who want to take i_lock no longer need to take sb_inode_list_lock to walk the list in the first place. This will simplify and optimize locking. - Could remove some nested trylock loops in dcache code - Could potentially simplify things a bit in VM land. Do not need to take the page lock to follow page->mapping. The downsides of this is the performance cost of using RCU. In a simple creat/unlink microbenchmark, performance drops by about 10% due to inability to reuse cache-hot slab objects. As iterations increase and RCU freeing starts kicking over, this increases to about 20%. In cases where inode lifetimes are longer (ie. many inodes may be allocated during the average life span of a single inode), a lot of this cache reuse is not applicable, so the regression caused by this patch is smaller. The cache-hot regression could largely be avoided by using SLAB_DESTROY_BY_RCU, however this adds some complexity to list walking and store-free path walking, so I prefer to implement this at a later date, if it is shown to be a win in real situations. I haven't found a regression in any non-micro benchmark so I doubt it will be a problem. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/ufs')
-rw-r--r--fs/ufs/super.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 2c47daed56da..2c61ac5d4e48 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1412,11 +1412,18 @@ static struct inode *ufs_alloc_inode(struct super_block *sb)
1412 return &ei->vfs_inode; 1412 return &ei->vfs_inode;
1413} 1413}
1414 1414
1415static void ufs_destroy_inode(struct inode *inode) 1415static void ufs_i_callback(struct rcu_head *head)
1416{ 1416{
1417 struct inode *inode = container_of(head, struct inode, i_rcu);
1418 INIT_LIST_HEAD(&inode->i_dentry);
1417 kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); 1419 kmem_cache_free(ufs_inode_cachep, UFS_I(inode));
1418} 1420}
1419 1421
1422static void ufs_destroy_inode(struct inode *inode)
1423{
1424 call_rcu(&inode->i_rcu, ufs_i_callback);
1425}
1426
1420static void init_once(void *foo) 1427static void init_once(void *foo)
1421{ 1428{
1422 struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; 1429 struct ufs_inode_info *ei = (struct ufs_inode_info *) foo;
x : y) #define MAX(x,y) (x > y ? x : y) #ifndef ACS_ULCORNER #define ACS_ULCORNER '+' #endif #ifndef ACS_LLCORNER #define ACS_LLCORNER '+' #endif #ifndef ACS_URCORNER #define ACS_URCORNER '+' #endif #ifndef ACS_LRCORNER #define ACS_LRCORNER '+' #endif #ifndef ACS_HLINE #define ACS_HLINE '-' #endif #ifndef ACS_VLINE #define ACS_VLINE '|' #endif #ifndef ACS_LTEE #define ACS_LTEE '+' #endif #ifndef ACS_RTEE #define ACS_RTEE '+' #endif #ifndef ACS_UARROW #define ACS_UARROW '^' #endif #ifndef ACS_DARROW #define ACS_DARROW 'v' #endif /* error return codes */ #define ERRDISPLAYTOOSMALL (KEY_MAX + 1) /* * Color definitions */ struct dialog_color { chtype atr; /* Color attribute */ int fg; /* foreground */ int bg; /* background */ int hl; /* highlight this item */ }; struct subtitle_list { struct subtitle_list *next; const char *text; }; struct dialog_info { const char *backtitle; struct subtitle_list *subtitles; struct dialog_color screen; struct dialog_color shadow; struct dialog_color dialog; struct dialog_color title; struct dialog_color border; struct dialog_color button_active; struct dialog_color button_inactive; struct dialog_color button_key_active; struct dialog_color button_key_inactive; struct dialog_color button_label_active; struct dialog_color button_label_inactive; struct dialog_color inputbox; struct dialog_color inputbox_border; struct dialog_color searchbox; struct dialog_color searchbox_title; struct dialog_color searchbox_border; struct dialog_color position_indicator; struct dialog_color menubox; struct dialog_color menubox_border; struct dialog_color item; struct dialog_color item_selected; struct dialog_color tag; struct dialog_color tag_selected; struct dialog_color tag_key; struct dialog_color tag_key_selected; struct dialog_color check; struct dialog_color check_selected; struct dialog_color uarrow; struct dialog_color darrow; }; /* * Global variables */ extern struct dialog_info dlg; extern char dialog_input_result[]; extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */ /* * Function prototypes */ /* item list as used by checklist and menubox */ void item_reset(void); void item_make(const char *fmt, ...); void item_add_str(const char *fmt, ...); void item_set_tag(char tag); void item_set_data(void *p); void item_set_selected(int val); int item_activate_selected(void); void *item_data(void); char item_tag(void); /* item list manipulation for lxdialog use */ #define MAXITEMSTR 200 struct dialog_item { char str[MAXITEMSTR]; /* prompt displayed */ char tag; void *data; /* pointer to menu item - used by menubox+checklist */ int selected; /* Set to 1 by dialog_*() function if selected. */ }; /* list of lialog_items */ struct dialog_list { struct dialog_item node; struct dialog_list *next; }; extern struct dialog_list *item_cur; extern struct dialog_list item_nil; extern struct dialog_list *item_head; int item_count(void); void item_set(int n); int item_n(void); const char *item_str(void); int item_is_selected(void); int item_is_tag(char tag); #define item_foreach() \ for (item_cur = item_head ? item_head: item_cur; \ item_cur && (item_cur != &item_nil); item_cur = item_cur->next) /* generic key handlers */ int on_key_esc(WINDOW *win); int on_key_resize(void); /* minimum (re)size values */ #define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */ #define CHECKLIST_WIDTH_MIN 6 #define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */ #define INPUTBOX_WIDTH_MIN 2 #define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */ #define MENUBOX_WIDTH_MIN 65 #define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */ #define TEXTBOX_WIDTH_MIN 8 #define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */ #define YESNO_WIDTH_MIN 4 #define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */ #define WINDOW_WIDTH_MIN 80 int init_dialog(const char *backtitle); void set_dialog_backtitle(const char *backtitle); void set_dialog_subtitles(struct subtitle_list *subtitles); void end_dialog(int x, int y); void attr_clear(WINDOW * win, int height, int width, chtype attr); void dialog_clear(void); void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); void print_button(WINDOW * win, const char *label, int y, int x, int selected); void print_title(WINDOW *dialog, const char *title, int width); void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, chtype border); void draw_shadow(WINDOW * win, int y, int x, int height, int width); int first_alpha(const char *string, const char *exempt); int dialog_yesno(const char *title, const char *prompt, int height, int width); int dialog_msgbox(const char *title, const char *prompt, int height, int width, int pause); typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void *_data); int dialog_textbox(const char *title, char *tbuf, int initial_height, int initial_width, int *keys, int *_vscroll, int *_hscroll, update_text_fn update_text, void *data); int dialog_menu(const char *title, const char *prompt, const void *selected, int *s_scroll); int dialog_checklist(const char *title, const char *prompt, int height, int width, int list_height); int dialog_inputbox(const char *title, const char *prompt, int height, int width, const char *init); /* * This is the base for fictitious keys, which activate * the buttons. * * Mouse-generated keys are the following: * -- the first 32 are used as numbers, in addition to '0'-'9' * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') * -- uppercase chars are used to invoke the button (M_EVENT + 'O') */ #define M_EVENT (KEY_MAX+1)