Skip to content
Snippets Groups Projects
Commit d4013e45 authored by Jinshan Xiong's avatar Jinshan Xiong
Browse files

recommit the patch for bug 5498.

parent 9527f5ce
No related branches found
No related tags found
No related merge requests found
MODULES := lustre
MODULES := lustre llite_lloop
lustre-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o rw.o lproc_llite.o namei.o symlink.o llite_mmap.o xattr.o statahead.o
llite_lloop-objs := lloop.o
ifeq ($(PATCHLEVEL),4)
lustre-objs += rw24.o super.o
else
......
......@@ -2236,10 +2236,17 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EXT3_IOC_SETVERSION_OLD:
case EXT3_IOC_SETVERSION:
*/
default:
default: {
int err;
if (LLIOC_STOP ==
ll_iocontrol_call(inode, file, cmd, arg, &err))
RETURN(err);
RETURN(obd_iocontrol(cmd, ll_i2obdexp(inode), 0, NULL,
(void *)arg));
}
}
}
loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
......@@ -2791,3 +2798,102 @@ struct inode_operations ll_file_inode_operations = {
.removexattr = ll_removexattr,
};
/* dynamic ioctl number support routins */
static struct llioc_ctl_data {
struct rw_semaphore ioc_sem;
struct list_head ioc_head;
} llioc = {
__RWSEM_INITIALIZER(llioc.ioc_sem),
CFS_LIST_HEAD_INIT(llioc.ioc_head)
};
struct llioc_data {
struct list_head iocd_list;
unsigned int iocd_size;
llioc_callback_t iocd_cb;
unsigned int iocd_count;
unsigned int iocd_cmd[0];
};
void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd)
{
unsigned int size;
struct llioc_data *in_data = NULL;
ENTRY;
if (cb == NULL || cmd == NULL ||
count > LLIOC_MAX_CMD || count < 0)
RETURN(NULL);
size = sizeof(*in_data) + count * sizeof(unsigned int);
OBD_ALLOC(in_data, size);
if (in_data == NULL)
RETURN(NULL);
memset(in_data, 0, sizeof(*in_data));
in_data->iocd_size = size;
in_data->iocd_cb = cb;
in_data->iocd_count = count;
memcpy(in_data->iocd_cmd, cmd, sizeof(unsigned int) * count);
down_write(&llioc.ioc_sem);
list_add_tail(&in_data->iocd_list, &llioc.ioc_head);
up_write(&llioc.ioc_sem);
RETURN(in_data);
}
void ll_iocontrol_unregister(void *magic)
{
struct llioc_data *tmp;
if (magic == NULL)
return;
down_write(&llioc.ioc_sem);
list_for_each_entry(tmp, &llioc.ioc_head, iocd_list) {
if (tmp == magic) {
unsigned int size = tmp->iocd_size;
list_del(&tmp->iocd_list);
up_write(&llioc.ioc_sem);
OBD_FREE(tmp, size);
return;
}
}
up_write(&llioc.ioc_sem);
CWARN("didn't find iocontrol register block with magic: %p\n", magic);
}
EXPORT_SYMBOL(ll_iocontrol_register);
EXPORT_SYMBOL(ll_iocontrol_unregister);
enum llioc_iter ll_iocontrol_call(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg, int *rcp)
{
enum llioc_iter ret = LLIOC_CONT;
struct llioc_data *data;
int rc = -EINVAL, i;
down_read(&llioc.ioc_sem);
list_for_each_entry(data, &llioc.ioc_head, iocd_list) {
for (i = 0; i < data->iocd_count; i++) {
if (cmd != data->iocd_cmd[i])
continue;
ret = data->iocd_cb(inode, file, cmd, arg, data, &rc);
break;
}
if (ret == LLIOC_STOP)
break;
}
up_read(&llioc.ioc_sem);
if (rcp)
*rcp = rc;
return ret;
}
......@@ -807,4 +807,51 @@ int ll_statahead_enter(struct inode *dir, struct dentry **dentry, int lookup);
void ll_statahead_exit(struct dentry *dentry, int result);
void ll_stop_statahead(struct inode *inode);
/* llite ioctl register support rountine */
#ifdef __KERNEL__
enum llioc_iter {
LLIOC_CONT = 0,
LLIOC_STOP
};
#define LLIOC_MAX_CMD 256
/*
* Rules to write a callback function:
*
* Parameters:
* @magic: Dynamic ioctl call routine will feed this vaule with the pointer
* returned to ll_iocontrol_register. Callback functions should use this
* data to check the potential collasion of ioctl cmd. If collasion is
* found, callback function should return LLIOC_CONT.
* @rcp: The result of ioctl command.
*
* Return values:
* If @magic matches the pointer returned by ll_iocontrol_data, the
* callback should return LLIOC_STOP; return LLIOC_STOP otherwise.
*/
typedef enum llioc_iter (*llioc_callback_t)(struct inode *inode,
struct file *file, unsigned int cmd, unsigned long arg,
void *magic, int *rcp);
enum llioc_iter ll_iocontrol_call(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg, int *rcp);
/* export functions */
/* Register ioctl block dynamatically for a regular file.
*
* @cmd: the array of ioctl command set
* @count: number of commands in the @cmd
* @cb: callback function, it will be called if an ioctl command is found to
* belong to the command list @cmd.
*
* Return vaule:
* A magic pointer will be returned if success;
* otherwise, NULL will be returned.
* */
void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd);
void ll_iocontrol_unregister(void *magic);
#endif
#endif /* LLITE_INTERNAL_H */
This diff is collapsed.
......@@ -615,6 +615,7 @@ void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count)
sbi->ll_stats_track_id == current->gid)
lprocfs_counter_add(sbi->ll_stats, op, count);
}
EXPORT_SYMBOL(ll_stats_ops_tally);
int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
struct super_block *sb, char *osc, char *mdc)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment