2 * (C) 2001 Clemson University and The University of Chicago
4 * Changes by Acxiom Corporation to add protocol version to kernel
5 * communication, Copyright Acxiom Corporation, 2005.
7 * See COPYING in top-level directory.
11 #include "orangefs-kernel.h"
12 #include "orangefs-dev-proto.h"
13 #include "orangefs-bufmap.h"
15 #include <linux/debugfs.h>
16 #include <linux/slab.h>
18 /* this file implements the /dev/pvfs2-req device node */
20 static int open_access_count
;
22 #define DUMP_DEVICE_ERROR() \
24 gossip_err("*****************************************************\n");\
25 gossip_err("ORANGEFS Device Error: You cannot open the device file "); \
26 gossip_err("\n/dev/%s more than once. Please make sure that\nthere " \
27 "are no ", ORANGEFS_REQDEVICE_NAME); \
28 gossip_err("instances of a program using this device\ncurrently " \
29 "running. (You must verify this!)\n"); \
30 gossip_err("For example, you can use the lsof program as follows:\n");\
31 gossip_err("'lsof | grep %s' (run this as root)\n", \
32 ORANGEFS_REQDEVICE_NAME); \
33 gossip_err(" open_access_count = %d\n", open_access_count); \
34 gossip_err("*****************************************************\n");\
37 static int hash_func(__u64 tag
, int table_size
)
39 return do_div(tag
, (unsigned int)table_size
);
42 static void orangefs_devreq_add_op(struct orangefs_kernel_op_s
*op
)
44 int index
= hash_func(op
->tag
, hash_table_size
);
46 spin_lock(&htable_ops_in_progress_lock
);
47 list_add_tail(&op
->list
, &htable_ops_in_progress
[index
]);
48 spin_unlock(&htable_ops_in_progress_lock
);
51 static struct orangefs_kernel_op_s
*orangefs_devreq_remove_op(__u64 tag
)
53 struct orangefs_kernel_op_s
*op
, *next
;
56 index
= hash_func(tag
, hash_table_size
);
58 spin_lock(&htable_ops_in_progress_lock
);
59 list_for_each_entry_safe(op
,
61 &htable_ops_in_progress
[index
],
65 spin_unlock(&htable_ops_in_progress_lock
);
70 spin_unlock(&htable_ops_in_progress_lock
);
74 static int orangefs_devreq_open(struct inode
*inode
, struct file
*file
)
78 if (!(file
->f_flags
& O_NONBLOCK
)) {
79 gossip_err("%s: device cannot be opened in blocking mode\n",
84 gossip_debug(GOSSIP_DEV_DEBUG
, "client-core: opening device\n");
85 mutex_lock(&devreq_mutex
);
87 if (open_access_count
== 0) {
88 ret
= generic_file_open(inode
, file
);
94 mutex_unlock(&devreq_mutex
);
98 gossip_debug(GOSSIP_DEV_DEBUG
,
99 "pvfs2-client-core: open device complete (ret = %d)\n",
104 /* Function for read() callers into the device */
105 static ssize_t
orangefs_devreq_read(struct file
*file
,
107 size_t count
, loff_t
*offset
)
109 struct orangefs_kernel_op_s
*op
, *temp
;
110 __s32 proto_ver
= ORANGEFS_KERNEL_PROTO_VERSION
;
111 static __s32 magic
= ORANGEFS_DEVREQ_MAGIC
;
112 struct orangefs_kernel_op_s
*cur_op
= NULL
;
115 /* We do not support blocking IO. */
116 if (!(file
->f_flags
& O_NONBLOCK
)) {
117 gossip_err("%s: blocking read from client-core.\n",
123 * The client will do an ioctl to find MAX_DEV_REQ_UPSIZE, then
124 * always read with that size buffer.
126 if (count
!= MAX_DEV_REQ_UPSIZE
) {
127 gossip_err("orangefs: client-core tried to read wrong size\n");
131 /* Get next op (if any) from top of list. */
132 spin_lock(&orangefs_request_list_lock
);
133 list_for_each_entry_safe(op
, temp
, &orangefs_request_list
, list
) {
135 /* This lock is held past the end of the loop when we break. */
136 spin_lock(&op
->lock
);
138 fsid
= fsid_of_op(op
);
139 if (fsid
!= ORANGEFS_FS_ID_NULL
) {
141 /* Skip ops whose filesystem needs to be mounted. */
142 ret
= fs_mount_pending(fsid
);
144 gossip_debug(GOSSIP_DEV_DEBUG
,
145 "orangefs: skipping op tag %llu %s\n",
146 llu(op
->tag
), get_opname_string(op
));
147 spin_unlock(&op
->lock
);
150 * Skip ops whose filesystem we don't know about unless
151 * it is being mounted.
153 /* XXX: is there a better way to detect this? */
154 } else if (ret
== -1 &&
156 ORANGEFS_VFS_OP_FS_MOUNT
||
158 ORANGEFS_VFS_OP_GETATTR
)) {
159 gossip_debug(GOSSIP_DEV_DEBUG
,
160 "orangefs: skipping op tag %llu %s\n",
161 llu(op
->tag
), get_opname_string(op
));
163 "orangefs: ERROR: fs_mount_pending %d\n",
165 spin_unlock(&op
->lock
);
170 * Either this op does not pertain to a filesystem, is mounting
171 * a filesystem, or pertains to a mounted filesystem. Let it
179 * At this point we either have a valid op and can continue or have not
180 * found an op and must ask the client to try again later.
183 spin_unlock(&orangefs_request_list_lock
);
187 gossip_debug(GOSSIP_DEV_DEBUG
, "orangefs: reading op tag %llu %s\n",
188 llu(cur_op
->tag
), get_opname_string(cur_op
));
191 * Such an op should never be on the list in the first place. If so, we
194 if (op_state_in_progress(cur_op
) || op_state_serviced(cur_op
)) {
195 gossip_err("orangefs: ERROR: Current op already queued.\n");
196 list_del(&cur_op
->list
);
197 spin_unlock(&cur_op
->lock
);
198 spin_unlock(&orangefs_request_list_lock
);
203 * Set the operation to be in progress and move it between lists since
204 * it has been sent to the client.
206 set_op_state_inprogress(cur_op
);
208 list_del(&cur_op
->list
);
209 spin_unlock(&orangefs_request_list_lock
);
210 orangefs_devreq_add_op(cur_op
);
211 spin_unlock(&cur_op
->lock
);
213 /* Push the upcall out. */
214 ret
= copy_to_user(buf
, &proto_ver
, sizeof(__s32
));
217 ret
= copy_to_user(buf
+sizeof(__s32
), &magic
, sizeof(__s32
));
220 ret
= copy_to_user(buf
+2 * sizeof(__s32
), &cur_op
->tag
, sizeof(__u64
));
223 ret
= copy_to_user(buf
+2*sizeof(__s32
)+sizeof(__u64
), &cur_op
->upcall
,
224 sizeof(struct orangefs_upcall_s
));
228 /* The client only asks to read one size buffer. */
229 return MAX_DEV_REQ_UPSIZE
;
232 * We were unable to copy the op data to the client. Put the op back in
233 * list. If client has crashed, the op will be purged later when the
234 * device is released.
236 gossip_err("orangefs: Failed to copy data to user space\n");
237 spin_lock(&orangefs_request_list_lock
);
238 spin_lock(&cur_op
->lock
);
239 set_op_state_waiting(cur_op
);
240 orangefs_devreq_remove_op(cur_op
->tag
);
241 list_add(&cur_op
->list
, &orangefs_request_list
);
242 spin_unlock(&cur_op
->lock
);
243 spin_unlock(&orangefs_request_list_lock
);
248 * Function for writev() callers into the device. Readdir related
249 * operations have an extra iovec containing info about objects
250 * contained in directories.
252 static ssize_t
orangefs_devreq_writev(struct file
*file
,
253 const struct iovec
*iov
,
257 struct orangefs_kernel_op_s
*op
= NULL
;
261 int num_remaining
= MAX_DEV_REQ_DOWNSIZE
;
263 /* num elements in iovec without trailer */
264 int notrailer_count
= 4;
266 * If there's a trailer, its iov index will be equal to
269 int trailer_index
= notrailer_count
;
270 int payload_size
= 0;
271 int returned_downcall_size
= 0;
275 ssize_t total_returned_size
= 0;
278 * There will always be at least notrailer_count iovecs, and
279 * when there's a trailer, one more than notrailer_count. Check
282 if (count
!= notrailer_count
&& count
!= (notrailer_count
+ 1)) {
283 gossip_err("%s: count:%zu: notrailer_count :%d:\n",
291 /* Copy the non-trailer iovec data into a device request buffer. */
292 buffer
= dev_req_alloc();
294 gossip_err("%s: dev_req_alloc failed.\n", __func__
);
298 for (i
= 0; i
< notrailer_count
; i
++) {
299 if (iov
[i
].iov_len
> num_remaining
) {
301 ("writev error: Freeing buffer and returning\n");
302 dev_req_release(buffer
);
305 ret
= copy_from_user(ptr
, iov
[i
].iov_base
, iov
[i
].iov_len
);
307 gossip_err("Failed to copy data from user space\n");
308 dev_req_release(buffer
);
311 num_remaining
-= iov
[i
].iov_len
;
312 ptr
+= iov
[i
].iov_len
;
313 payload_size
+= iov
[i
].iov_len
;
315 total_returned_size
= payload_size
;
317 /* these elements are currently 8 byte aligned (8 bytes for (version +
318 * magic) 8 bytes for tag). If you add another element, either
319 * make it 8 bytes big, or use get_unaligned when asigning.
322 proto_ver
= *((__s32
*) ptr
); /* unused */
323 ptr
+= sizeof(__s32
);
325 magic
= *((__s32
*) ptr
);
326 ptr
+= sizeof(__s32
);
328 tag
= *((__u64
*) ptr
);
329 ptr
+= sizeof(__u64
);
331 if (magic
!= ORANGEFS_DEVREQ_MAGIC
) {
332 gossip_err("Error: Device magic number does not match.\n");
333 dev_req_release(buffer
);
337 op
= orangefs_devreq_remove_op(tag
);
339 /* Increase ref count! */
342 /* calculate the size of the returned downcall. */
343 returned_downcall_size
=
344 payload_size
- (2 * sizeof(__s32
) + sizeof(__u64
));
346 /* copy the passed in downcall into the op */
347 if (returned_downcall_size
==
348 sizeof(struct orangefs_downcall_s
)) {
349 memcpy(&op
->downcall
,
351 sizeof(struct orangefs_downcall_s
));
353 gossip_err("%s: returned downcall size:%d: \n",
355 returned_downcall_size
);
356 dev_req_release(buffer
);
361 /* Don't tolerate an unexpected trailer iovec. */
362 if ((op
->downcall
.trailer_size
== 0) &&
363 (count
!= notrailer_count
)) {
364 gossip_err("%s: unexpected trailer iovec.\n",
366 dev_req_release(buffer
);
371 /* Don't consider the trailer if there's a bad status. */
372 if (op
->downcall
.status
!= 0)
375 /* get the trailer if there is one. */
376 if (op
->downcall
.trailer_size
== 0)
379 gossip_debug(GOSSIP_DEV_DEBUG
,
380 "%s: op->downcall.trailer_size %lld\n",
382 op
->downcall
.trailer_size
);
385 * Bail if we think think there should be a trailer, but
386 * there's no iovec for it.
388 if (count
!= (notrailer_count
+ 1)) {
389 gossip_err("%s: trailer_size:%lld: count:%zu:\n",
391 op
->downcall
.trailer_size
,
393 dev_req_release(buffer
);
398 /* Verify that trailer_size is accurate. */
399 if (op
->downcall
.trailer_size
!= iov
[trailer_index
].iov_len
) {
400 gossip_err("%s: trailer_size:%lld: != iov_len:%zd:\n",
402 op
->downcall
.trailer_size
,
403 iov
[trailer_index
].iov_len
);
404 dev_req_release(buffer
);
409 total_returned_size
+= iov
[trailer_index
].iov_len
;
412 * Allocate a buffer, copy the trailer bytes into it and
413 * attach it to the downcall.
415 op
->downcall
.trailer_buf
= vmalloc(iov
[trailer_index
].iov_len
);
416 if (op
->downcall
.trailer_buf
!= NULL
) {
417 gossip_debug(GOSSIP_DEV_DEBUG
, "vmalloc: %p\n",
418 op
->downcall
.trailer_buf
);
419 ret
= copy_from_user(op
->downcall
.trailer_buf
,
420 iov
[trailer_index
].iov_base
,
421 iov
[trailer_index
].iov_len
);
423 gossip_err("%s: Failed to copy trailer.\n",
425 dev_req_release(buffer
);
426 gossip_debug(GOSSIP_DEV_DEBUG
,
428 op
->downcall
.trailer_buf
);
429 vfree(op
->downcall
.trailer_buf
);
430 op
->downcall
.trailer_buf
= NULL
;
435 gossip_err("writev: could not vmalloc for trailer!\n");
436 dev_req_release(buffer
);
443 /* if this operation is an I/O operation we need to wait
444 * for all data to be copied before we can return to avoid
445 * buffer corruption and races that can pull the buffers
448 * Essentially we're synchronizing with other parts of the
449 * vfs implicitly by not allowing the user space
450 * application reading/writing this device to return until
451 * the buffers are done being used.
453 if (op
->upcall
.type
== ORANGEFS_VFS_OP_FILE_IO
) {
455 DEFINE_WAIT(wait_entry
);
458 * tell the vfs op waiting on a waitqueue
459 * that this op is done
461 spin_lock(&op
->lock
);
462 set_op_state_serviced(op
);
463 spin_unlock(&op
->lock
);
465 wake_up_interruptible(&op
->waitq
);
468 spin_lock(&op
->lock
);
469 prepare_to_wait_exclusive(
470 &op
->io_completion_waitq
,
473 if (op
->io_completed
) {
474 spin_unlock(&op
->lock
);
477 spin_unlock(&op
->lock
);
479 if (!signal_pending(current
)) {
481 MSECS_TO_JIFFIES(1000 *
483 if (!schedule_timeout(timeout
)) {
484 gossip_debug(GOSSIP_DEV_DEBUG
,
493 gossip_debug(GOSSIP_DEV_DEBUG
,
494 "%s: signal on I/O wait, aborting\n",
499 spin_lock(&op
->lock
);
500 finish_wait(&op
->io_completion_waitq
, &wait_entry
);
501 spin_unlock(&op
->lock
);
503 /* NOTE: for I/O operations we handle releasing the op
504 * object except in the case of timeout. the reason we
505 * can't free the op in timeout cases is that the op
506 * service logic in the vfs retries operations using
507 * the same op ptr, thus it can't be freed.
514 * tell the vfs op waiting on a waitqueue that
517 spin_lock(&op
->lock
);
518 set_op_state_serviced(op
);
519 spin_unlock(&op
->lock
);
521 * for every other operation (i.e. non-I/O), we need to
522 * wake up the callers for downcall completion
525 wake_up_interruptible(&op
->waitq
);
528 /* ignore downcalls that we're not interested in */
529 gossip_debug(GOSSIP_DEV_DEBUG
,
530 "WARNING: No one's waiting for tag %llu\n",
534 dev_req_release(buffer
);
536 return total_returned_size
;
539 static ssize_t
orangefs_devreq_write_iter(struct kiocb
*iocb
,
540 struct iov_iter
*iter
)
542 return orangefs_devreq_writev(iocb
->ki_filp
,
548 /* Returns whether any FS are still pending remounted */
549 static int mark_all_pending_mounts(void)
552 struct orangefs_sb_info_s
*orangefs_sb
= NULL
;
554 spin_lock(&orangefs_superblocks_lock
);
555 list_for_each_entry(orangefs_sb
, &orangefs_superblocks
, list
) {
556 /* All of these file system require a remount */
557 orangefs_sb
->mount_pending
= 1;
560 spin_unlock(&orangefs_superblocks_lock
);
565 * Determine if a given file system needs to be remounted or not
566 * Returns -1 on error
567 * 0 if already mounted
570 int fs_mount_pending(__s32 fsid
)
572 int mount_pending
= -1;
573 struct orangefs_sb_info_s
*orangefs_sb
= NULL
;
575 spin_lock(&orangefs_superblocks_lock
);
576 list_for_each_entry(orangefs_sb
, &orangefs_superblocks
, list
) {
577 if (orangefs_sb
->fs_id
== fsid
) {
578 mount_pending
= orangefs_sb
->mount_pending
;
582 spin_unlock(&orangefs_superblocks_lock
);
583 return mount_pending
;
587 * NOTE: gets called when the last reference to this device is dropped.
588 * Using the open_access_count variable, we enforce a reference count
589 * on this file so that it can be opened by only one process at a time.
590 * the devreq_mutex is used to make sure all i/o has completed
591 * before we call orangefs_bufmap_finalize, and similar such tricky
594 static int orangefs_devreq_release(struct inode
*inode
, struct file
*file
)
598 gossip_debug(GOSSIP_DEV_DEBUG
,
599 "%s:pvfs2-client-core: exiting, closing device\n",
602 mutex_lock(&devreq_mutex
);
603 if (orangefs_get_bufmap_init())
604 orangefs_bufmap_finalize();
608 unmounted
= mark_all_pending_mounts();
609 gossip_debug(GOSSIP_DEV_DEBUG
, "ORANGEFS Device Close: Filesystem(s) %s\n",
610 (unmounted
? "UNMOUNTED" : "MOUNTED"));
611 mutex_unlock(&devreq_mutex
);
614 * Walk through the list of ops in the request list, mark them
615 * as purged and wake them up.
619 * Walk through the hash table of in progress operations; mark
620 * them as purged and wake them up
622 purge_inprogress_ops();
623 gossip_debug(GOSSIP_DEV_DEBUG
,
624 "pvfs2-client-core: device close complete\n");
628 int is_daemon_in_service(void)
633 * What this function does is checks if client-core is alive
634 * based on the access count we maintain on the device.
636 mutex_lock(&devreq_mutex
);
637 in_service
= open_access_count
== 1 ? 0 : -EIO
;
638 mutex_unlock(&devreq_mutex
);
642 static inline long check_ioctl_command(unsigned int command
)
644 /* Check for valid ioctl codes */
645 if (_IOC_TYPE(command
) != ORANGEFS_DEV_MAGIC
) {
646 gossip_err("device ioctl magic numbers don't match! Did you rebuild pvfs2-client-core/libpvfs2? [cmd %x, magic %x != %x]\n",
652 /* and valid ioctl commands */
653 if (_IOC_NR(command
) >= ORANGEFS_DEV_MAXNR
|| _IOC_NR(command
) <= 0) {
654 gossip_err("Invalid ioctl command number [%d >= %d]\n",
655 _IOC_NR(command
), ORANGEFS_DEV_MAXNR
);
661 static long dispatch_ioctl_command(unsigned int command
, unsigned long arg
)
663 static __s32 magic
= ORANGEFS_DEVREQ_MAGIC
;
664 static __s32 max_up_size
= MAX_DEV_REQ_UPSIZE
;
665 static __s32 max_down_size
= MAX_DEV_REQ_DOWNSIZE
;
666 struct ORANGEFS_dev_map_desc user_desc
;
668 struct dev_mask_info_s mask_info
= { 0 };
669 struct dev_mask2_info_s mask2_info
= { 0, 0 };
670 int upstream_kmod
= 1;
671 struct list_head
*tmp
= NULL
;
672 struct orangefs_sb_info_s
*orangefs_sb
= NULL
;
674 /* mtmoore: add locking here */
677 case ORANGEFS_DEV_GET_MAGIC
:
678 return ((put_user(magic
, (__s32 __user
*) arg
) == -EFAULT
) ?
681 case ORANGEFS_DEV_GET_MAX_UPSIZE
:
682 return ((put_user(max_up_size
,
683 (__s32 __user
*) arg
) == -EFAULT
) ?
686 case ORANGEFS_DEV_GET_MAX_DOWNSIZE
:
687 return ((put_user(max_down_size
,
688 (__s32 __user
*) arg
) == -EFAULT
) ?
691 case ORANGEFS_DEV_MAP
:
692 ret
= copy_from_user(&user_desc
,
693 (struct ORANGEFS_dev_map_desc __user
*)
695 sizeof(struct ORANGEFS_dev_map_desc
));
696 if (orangefs_get_bufmap_init()) {
701 orangefs_bufmap_initialize(&user_desc
);
703 case ORANGEFS_DEV_REMOUNT_ALL
:
704 gossip_debug(GOSSIP_DEV_DEBUG
,
705 "%s: got ORANGEFS_DEV_REMOUNT_ALL\n",
709 * remount all mounted orangefs volumes to regain the lost
710 * dynamic mount tables (if any) -- NOTE: this is done
711 * without keeping the superblock list locked due to the
712 * upcall/downcall waiting. also, the request semaphore is
713 * used to ensure that no operations will be serviced until
714 * all of the remounts are serviced (to avoid ops between
717 ret
= mutex_lock_interruptible(&request_mutex
);
720 gossip_debug(GOSSIP_DEV_DEBUG
,
721 "%s: priority remount in progress\n",
723 list_for_each(tmp
, &orangefs_superblocks
) {
726 struct orangefs_sb_info_s
,
728 if (orangefs_sb
&& (orangefs_sb
->sb
)) {
729 gossip_debug(GOSSIP_DEV_DEBUG
,
730 "%s: Remounting SB %p\n",
734 ret
= orangefs_remount(orangefs_sb
->sb
);
736 gossip_debug(GOSSIP_DEV_DEBUG
,
737 "SB %p remount failed\n",
743 gossip_debug(GOSSIP_DEV_DEBUG
,
744 "%s: priority remount complete\n",
746 mutex_unlock(&request_mutex
);
749 case ORANGEFS_DEV_UPSTREAM
:
750 ret
= copy_to_user((void __user
*)arg
,
752 sizeof(upstream_kmod
));
759 case ORANGEFS_DEV_CLIENT_MASK
:
760 ret
= copy_from_user(&mask2_info
,
762 sizeof(struct dev_mask2_info_s
));
767 client_debug_mask
.mask1
= mask2_info
.mask1_value
;
768 client_debug_mask
.mask2
= mask2_info
.mask2_value
;
770 pr_info("%s: client debug mask has been been received "
773 (unsigned long long)client_debug_mask
.mask1
,
774 (unsigned long long)client_debug_mask
.mask2
);
778 case ORANGEFS_DEV_CLIENT_STRING
:
779 ret
= copy_from_user(&client_debug_array_string
,
781 ORANGEFS_MAX_DEBUG_STRING_LEN
);
783 pr_info("%s: CLIENT_STRING: copy_from_user failed\n",
788 pr_info("%s: client debug array string has been received.\n",
791 if (!help_string_initialized
) {
793 /* Free the "we don't know yet" default string... */
794 kfree(debug_help_string
);
796 /* build a proper debug help string */
797 if (orangefs_prepare_debugfs_help_string(0)) {
798 gossip_err("%s: no debug help string \n",
803 /* Replace the boilerplate boot-time debug-help file. */
804 debugfs_remove(help_file_dentry
);
808 ORANGEFS_KMOD_DEBUG_HELP_FILE
,
814 if (!help_file_dentry
) {
815 gossip_err("%s: debugfs_create_file failed for"
818 ORANGEFS_KMOD_DEBUG_HELP_FILE
);
823 debug_mask_to_string(&client_debug_mask
, 1);
825 debugfs_remove(client_debug_dentry
);
827 orangefs_client_debug_init();
829 help_string_initialized
++;
833 case ORANGEFS_DEV_DEBUG
:
834 ret
= copy_from_user(&mask_info
,
841 if (mask_info
.mask_type
== KERNEL_MASK
) {
842 if ((mask_info
.mask_value
== 0)
843 && (kernel_mask_set_mod_init
)) {
845 * the kernel debug mask was set when the
846 * kernel module was loaded; don't override
847 * it if the client-core was started without
848 * a value for ORANGEFS_KMODMASK.
852 debug_mask_to_string(&mask_info
.mask_value
,
853 mask_info
.mask_type
);
854 gossip_debug_mask
= mask_info
.mask_value
;
855 pr_info("%s: kernel debug mask has been modified to "
859 (unsigned long long)gossip_debug_mask
);
860 } else if (mask_info
.mask_type
== CLIENT_MASK
) {
861 debug_mask_to_string(&mask_info
.mask_value
,
862 mask_info
.mask_type
);
863 pr_info("%s: client debug mask has been modified to"
867 llu(mask_info
.mask_value
));
869 gossip_lerr("Invalid mask type....\n");
881 static long orangefs_devreq_ioctl(struct file
*file
,
882 unsigned int command
, unsigned long arg
)
886 /* Check for properly constructed commands */
887 ret
= check_ioctl_command(command
);
891 return (int)dispatch_ioctl_command(command
, arg
);
894 #ifdef CONFIG_COMPAT /* CONFIG_COMPAT is in .config */
896 /* Compat structure for the ORANGEFS_DEV_MAP ioctl */
897 struct ORANGEFS_dev_map_desc32
{
904 static unsigned long translate_dev_map26(unsigned long args
, long *error
)
906 struct ORANGEFS_dev_map_desc32 __user
*p32
= (void __user
*)args
;
908 * Depending on the architecture, allocate some space on the
909 * user-call-stack based on our expected layout.
911 struct ORANGEFS_dev_map_desc __user
*p
=
912 compat_alloc_user_space(sizeof(*p
));
916 /* get the ptr from the 32 bit user-space */
917 if (get_user(addr
, &p32
->ptr
))
919 /* try to put that into a 64-bit layout */
920 if (put_user(compat_ptr(addr
), &p
->ptr
))
922 /* copy the remaining fields */
923 if (copy_in_user(&p
->total_size
, &p32
->total_size
, sizeof(__s32
)))
925 if (copy_in_user(&p
->size
, &p32
->size
, sizeof(__s32
)))
927 if (copy_in_user(&p
->count
, &p32
->count
, sizeof(__s32
)))
929 return (unsigned long)p
;
936 * 32 bit user-space apps' ioctl handlers when kernel modules
937 * is compiled as a 64 bit one
939 static long orangefs_devreq_compat_ioctl(struct file
*filp
, unsigned int cmd
,
943 unsigned long arg
= args
;
945 /* Check for properly constructed commands */
946 ret
= check_ioctl_command(cmd
);
949 if (cmd
== ORANGEFS_DEV_MAP
) {
951 * convert the arguments to what we expect internally
954 arg
= translate_dev_map26(args
, &ret
);
956 gossip_err("Could not translate dev map\n");
960 /* no other ioctl requires translation */
961 return dispatch_ioctl_command(cmd
, arg
);
964 #endif /* CONFIG_COMPAT is in .config */
967 * The following two ioctl32 functions had been refactored into the above
968 * CONFIG_COMPAT ifdef, but that was an over simplification that was
969 * not noticed until we tried to compile on power pc...
971 #if (defined(CONFIG_COMPAT) && !defined(HAVE_REGISTER_IOCTL32_CONVERSION)) || !defined(CONFIG_COMPAT)
972 static int orangefs_ioctl32_init(void)
977 static void orangefs_ioctl32_cleanup(void)
983 /* the assigned character device major number */
984 static int orangefs_dev_major
;
987 * Initialize orangefs device specific state:
988 * Must be called at module load time only
990 int orangefs_dev_init(void)
994 /* register the ioctl32 sub-system */
995 ret
= orangefs_ioctl32_init();
999 /* register orangefs-req device */
1000 orangefs_dev_major
= register_chrdev(0,
1001 ORANGEFS_REQDEVICE_NAME
,
1002 &orangefs_devreq_file_operations
);
1003 if (orangefs_dev_major
< 0) {
1004 gossip_debug(GOSSIP_DEV_DEBUG
,
1005 "Failed to register /dev/%s (error %d)\n",
1006 ORANGEFS_REQDEVICE_NAME
, orangefs_dev_major
);
1007 orangefs_ioctl32_cleanup();
1008 return orangefs_dev_major
;
1011 gossip_debug(GOSSIP_DEV_DEBUG
,
1012 "*** /dev/%s character device registered ***\n",
1013 ORANGEFS_REQDEVICE_NAME
);
1014 gossip_debug(GOSSIP_DEV_DEBUG
, "'mknod /dev/%s c %d 0'.\n",
1015 ORANGEFS_REQDEVICE_NAME
, orangefs_dev_major
);
1019 void orangefs_dev_cleanup(void)
1021 unregister_chrdev(orangefs_dev_major
, ORANGEFS_REQDEVICE_NAME
);
1022 gossip_debug(GOSSIP_DEV_DEBUG
,
1023 "*** /dev/%s character device unregistered ***\n",
1024 ORANGEFS_REQDEVICE_NAME
);
1025 /* unregister the ioctl32 sub-system */
1026 orangefs_ioctl32_cleanup();
1029 static unsigned int orangefs_devreq_poll(struct file
*file
,
1030 struct poll_table_struct
*poll_table
)
1032 int poll_revent_mask
= 0;
1034 if (open_access_count
== 1) {
1035 poll_wait(file
, &orangefs_request_list_waitq
, poll_table
);
1037 spin_lock(&orangefs_request_list_lock
);
1038 if (!list_empty(&orangefs_request_list
))
1039 poll_revent_mask
|= POLL_IN
;
1040 spin_unlock(&orangefs_request_list_lock
);
1042 return poll_revent_mask
;
1045 const struct file_operations orangefs_devreq_file_operations
= {
1046 .owner
= THIS_MODULE
,
1047 .read
= orangefs_devreq_read
,
1048 .write_iter
= orangefs_devreq_write_iter
,
1049 .open
= orangefs_devreq_open
,
1050 .release
= orangefs_devreq_release
,
1051 .unlocked_ioctl
= orangefs_devreq_ioctl
,
1053 #ifdef CONFIG_COMPAT /* CONFIG_COMPAT is in .config */
1054 .compat_ioctl
= orangefs_devreq_compat_ioctl
,
1056 .poll
= orangefs_devreq_poll