diff --git a/kernel/rros/clock.rs b/kernel/rros/clock.rs index c91c3082e761c..fa287f0cd3b36 100644 --- a/kernel/rros/clock.rs +++ b/kernel/rros/clock.rs @@ -546,7 +546,7 @@ pub static mut RROS_CLOCK_FACTORY: SpinLock = unsafe { dispose: Some(clock_factory_dispose), attrs: None, //sysfs::attribute_group::new(), flags: factory::RrosFactoryType::Invalid, - inside: Some(factory::RrosFactoryInside { + inside: factory::RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -559,7 +559,7 @@ pub static mut RROS_CLOCK_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; @@ -1028,7 +1028,7 @@ impl FileOperations for ClockOps { } } -pub fn clock_factory_dispose(ele: factory::RrosElement) {} +pub fn clock_factory_dispose(ele: &mut factory::RrosElement) {} fn timer_needs_enqueuing(timer: *mut RrosTimer) -> bool { unsafe { diff --git a/kernel/rros/control.rs b/kernel/rros/control.rs index dbccb3d6e28ce..4e6606cf86123 100644 --- a/kernel/rros/control.rs +++ b/kernel/rros/control.rs @@ -28,7 +28,7 @@ pub static mut RROS_CONTROL_FACTORY: SpinLock = unsafe { dispose: None, attrs: None, flags: crate::factory::RrosFactoryType::SINGLE, - inside: Some(RrosFactoryInside { + inside: RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -41,7 +41,7 @@ pub static mut RROS_CONTROL_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; diff --git a/kernel/rros/factory.rs b/kernel/rros/factory.rs index 2beaa4cfa7503..1d20cd178cf73 100644 --- a/kernel/rros/factory.rs +++ b/kernel/rros/factory.rs @@ -3,7 +3,11 @@ use core::{ result::Result::Ok, }; -use crate::{clock, control, file::RrosFileBinding, observable, poll, proxy, thread, xbuf}; +use crate::{ + clock, control, + file::{rros_release_file, RrosFileBinding}, + observable, poll, proxy, thread, xbuf, +}; use alloc::rc::Rc; @@ -16,19 +20,24 @@ use kernel::{ file_operations::{FileOpener, FileOperations, IoctlCommand}, fs::{self, Filename}, io_buffer::IoBufferWriter, - irq_work, kernelh, + irq_work::{self, IrqWork}, + kernelh, prelude::*, + premmpt::running_inband, rbtree, spinlock_init, str::CStr, sync::{Lock, SpinLock}, sysfs, types, uidgid::{self, KgidT, KuidT}, - workqueue, ThisModule, + workqueue::{self, Work}, + ThisModule, }; extern "C" { #[allow(improper_ctypes)] fn rust_helper_put_user(val: u32, ptr: *mut u32) -> c_types::c_int; + fn rust_helper_rcu_read_lock(); + fn rust_helper_rcu_read_unlock(); } type FundleT = u32; @@ -162,10 +171,10 @@ pub struct RrosFactory { state_offp: &u32, ) -> Rc>, >, - pub dispose: Option, + pub dispose: Option, pub attrs: Option, // Use an `Option` for the time being. pub flags: RrosFactoryType, - pub inside: Option, + pub inside: RrosFactoryInside, // pub fops: PhantomData, } @@ -178,7 +187,7 @@ pub static mut RROS_FACTORY: SpinLock = unsafe { dispose: None, attrs: None, //sysfs::attribute_group::new(), flags: RrosFactoryType::Invalid, - inside: Some(RrosFactoryInside { + inside: RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -191,7 +200,7 @@ pub static mut RROS_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; @@ -252,7 +261,122 @@ impl RrosElement { pointer: 0 as *mut u8, }) } + + /// `remove_element_device`: Remove a element device from hash list + /// and unregister this device. + #[allow(dead_code)] + pub fn remove_element_device(&mut self) { + let fac = unsafe { &mut *(self.factory.locked_data().get()) }; + // SAFETY: If self.dev is None, it will panic. But when we + // call this function, we make sure there is a device in element. + // So it is safe to unwrap. + let dev = self.dev.as_mut().unwrap(); + dev.unregister(); + + if self.is_public() { + drop(self.cdev.take()); + } + + { + let _guard = fac.inside.hash_lock.as_ref().unwrap().lock(); + self.hash.hash_del(); + } + } + + /// `is_public`: If element is public return ture + #[allow(dead_code)] + #[inline] + fn is_public(&self) -> bool { + self.clone_flags & RROS_CLONE_PUBLIC != 0x0 + } + + /// `__do_put_element`: Delete an element + pub fn __do_put_element(&mut self) { + extern "C" { + fn rust_helper_synchronize_rcu(); + } + let fac = unsafe { &*(self.factory.locked_data().get()) }; + if self.dev.is_none() { + fac.dispose.unwrap()(self); + } + + /* + * self->minor won't be free for use until rros_destroy_element() + * is called from the disposal handler, so there is no risk of + * reusing it too early. + */ + self.remove_element_device(); + + /* + * Serialize with rros_open_element(). + */ + unsafe { + rust_helper_synchronize_rcu(); + } + + fac.dispose.unwrap()(self); + } + + #[allow(dead_code)] + fn do_put_element_work(work: *mut Work) { + let e = + unsafe { &mut *(kernel::container_of!(work, RrosElement, work) as *mut RrosElement) }; + e.__do_put_element(); + } + + #[allow(dead_code)] + unsafe extern "C" fn do_put_element_irq(work: *mut IrqWork) { + let e = unsafe { + &mut *(kernel::container_of!(work, RrosElement, irq_work) as *mut RrosElement) + }; + workqueue::init_work(&mut e.work as *mut Work, Self::do_put_element_work); + unsafe { + workqueue::queue_work_on( + bindings::WORK_CPU_UNBOUND as i32, + bindings::system_wq, + &mut e.work as *mut Work, + ); + } + } + + /// `do_put_element`: Delete an element + pub fn do_put_element(&mut self) { + extern "C" { + fn rust_helper_hard_irqs_disabled() -> bool; + } + if running_inband().is_err() || unsafe { rust_helper_hard_irqs_disabled() } { + let res = self.irq_work.init_irq_work(Self::do_put_element_irq); + if res.is_err() { + pr_debug!("RrosElement: [do_put_element]: init_irq_work error"); + } + let res = self.irq_work.irq_work_queue(); + if res.is_err() { + pr_debug!("RrosElement: [do_put_element]: irq_work_queue error"); + } + } else { + self.__do_put_element(); + } + } + + /// `put_element`: Delete an element + #[allow(dead_code)] + pub fn put_element(&mut self) { + let flags = self.ref_lock.irq_lock_noguard(); + if self.refs == 0 { + pr_debug!("Warning: rros_open_element: e->refs == 0"); + self.ref_lock.irq_unlock_noguard(flags); + } else { + self.refs -= 1; + if self.refs == 0 { + self.zombie = true; + self.ref_lock.irq_unlock_noguard(flags); + self.do_put_element(); + return; + } + } + } } + pub struct RrosElementfpriv { pub filp: Option, pub efd: file::FileDescriptorReservation, @@ -296,7 +420,7 @@ impl device::Devnode for FactoryTypeDevnode { // TODO: currently we use raw pointer let element: Option<&RrosElement> = dev.get_drvdata(); if let Some(e) = element { - let inside = unsafe { (*(e.factory.locked_data().get())).inside.as_ref().unwrap() }; + let inside = unsafe { &(*(e.factory.locked_data().get())).inside }; if let Some(uid) = uid { if let Some(e_uid) = inside.kuid.as_ref() { *uid = *e_uid; @@ -321,7 +445,7 @@ fn create_element_device( e: Rc>, fac: &'static mut SpinLock, ) -> Result { - let mut fac_lock = unsafe { (*fac.locked_data().get()).inside.as_mut() }; + let inside = unsafe { &mut (*fac.locked_data().get()).inside }; let mut rdev: class::DevT = class::DevT::new(0); let _hlen: u64 = fs::hashlen_string( @@ -329,26 +453,19 @@ fn create_element_device( e.clone().borrow_mut().devname.as_mut().unwrap() as *mut Filename, ); - let _res = match fac_lock { - Some(ref mut inside) => { - let _ret = inside.hash_lock.as_ref().unwrap().lock(); + let _ret = inside.hash_lock.as_ref().unwrap().lock(); - // hash_for_each_possible(fac->name_hash, n, hash, hlen) - // if (!strcmp(n->devname->name, e->devname->name)) { - // mutex_unlock(&fac->hash_lock); - // goto fail_hash; - // } + // hash_for_each_possible(fac->name_hash, n, hash, hlen) + // if (!strcmp(n->devname->name, e->devname->name)) { + // mutex_unlock(&fac->hash_lock); + // goto fail_hash; + // } - // hash_add(fac->name_hash, &e->hash, hlen); + // hash_add(fac->name_hash, &e->hash, hlen); - unsafe { - inside.hash_lock.as_ref().unwrap().unlock(); - } - - 0 - } - None => 1, - }; + unsafe { + inside.hash_lock.as_ref().unwrap().unlock(); + } let _res = do_element_visibility(e.clone(), fac, &mut rdev); if !rros_element_is_public(e.clone()) && !rros_element_has_coredev(e.clone()) { @@ -398,11 +515,6 @@ fn do_element_visibility( fac: &'static mut SpinLock, _rdev: &mut class::DevT, ) -> Result { - // static int do_element_visibility(struct rros_element *e, - // struct rros_factory *fac, - // dev_t *rdev) - // { - let e_clone = e.clone(); // let core_dev_res = rros_element_has_coredev(e.clone()); @@ -471,15 +583,8 @@ fn do_element_visibility( // * Create a private user element, passing the real fops so // * that FMODE_CAN_READ/WRITE are set accordingly by the vfs. // */ - // let reg = unsafe{(*fac.locked_data().get()).inside.as_mut().unwrap().register.as_mut()}; - let reg = unsafe { - (*fac.locked_data().get()) - .inside - .as_mut() - .unwrap() - .register - .as_mut() - }; + // let reg = unsafe{(*fac.locked_data().get()).inside.register.as_mut()}; + let reg = unsafe { (*fac.locked_data().get()).inside.register.as_mut() }; // let reg = unsafe{&mut crate::Rros::factory}; let inner = reg.unwrap().inner.as_ref(); let cdev = (inner.unwrap().cdevs[0]).as_ref(); @@ -631,6 +736,15 @@ pub fn bind_file_to_element( // } } +#[allow(dead_code)] +pub fn unbind_file_to_element(filp: &File) -> *mut RrosElement { + let fbind = unsafe { (*filp.get_ptr()).private_data as *mut RrosFileBinding }; + let e = unsafe { (*fbind).element }; + + let _res = unsafe { rros_release_file(&mut (*fbind).rfile.borrow_mut()) }; + e +} + pub fn rros_create_core_element_device( e: Rc>, fac: &'static mut SpinLock, @@ -685,35 +799,31 @@ pub fn rros_init_element( fac: &'static mut SpinLock, clone_flags: i32, ) -> Result { - let mut minor = 0; + let mut minor; let mut fac_lock = fac.lock(); let nrdev = fac_lock.nrdev; - let _res = match fac_lock.inside { - Some(ref mut inside) => { - loop { - let minor_map; - if inside.minor_map.is_none() { - return Err(kernel::Error::EINVAL); - } - minor_map = inside.minor_map.unwrap(); - - minor = bitmap::find_first_zero_bit( - minor_map as *mut u8 as *const c_types::c_ulong, - nrdev as u64, - ); - if minor >= nrdev as u64 { - pr_err!("out of factory number"); - return Err(kernel::Error::EINVAL); - } - if !bitmap::test_and_set_bit(minor, minor_map as *mut c_types::c_ulong) { - break; - } - } - 0 + let inside: &mut RrosFactoryInside = &mut fac_lock.inside; + loop { + let minor_map; + if inside.minor_map.is_none() { + return Err(kernel::Error::EINVAL); } - None => 1, - }; + minor_map = inside.minor_map.unwrap(); + + minor = bitmap::find_first_zero_bit( + minor_map as *mut u8 as *const c_types::c_ulong, + nrdev as u64, + ); + if minor >= nrdev as u64 { + pr_err!("out of factory number"); + return Err(kernel::Error::EINVAL); + } + if !bitmap::test_and_set_bit(minor, minor_map as *mut c_types::c_ulong) { + break; + } + } + unsafe { fac.unlock(); } @@ -771,170 +881,161 @@ fn rros_create_factory( let name = fac_lock.name; let nrdev = fac_lock.nrdev; - let res = match fac_lock.inside { - Some(ref mut inside) => { - let mut idevname = CStr::from_bytes_with_nul("clone\0".as_bytes())?; - if let RrosFactoryType::SINGLE = flag { - // RROS_FACTORY_SINGLE - idevname = name; - inside.class = Some(rros_class.clone()); - inside.minor_map = Some(0); - inside.sub_rdev = Some(class::DevT::new(0)); - match idevname.to_str() { - Ok("control") => { - chrdev_reg.as_mut().register::()?; - } - Ok("poll") => { - chrdev_reg.as_mut().register::()?; - } - Ok(_) => { - pr_alert!("not yet implemented"); - } - Err(_e) => { - pr_err!("should not meet here"); - } - } - } else { - // create_element_class - inside.minor_map = - Some(bitmap_zalloc(nrdev.try_into().unwrap(), bindings::GFP_KERNEL) as u64); - if inside.minor_map == Some(0) { - return Err(kernel::Error::EINVAL); - } - - inside.class = Some(Arc::try_new(class::Class::new( - this_module, - name.as_char_ptr(), - )?)?); - let mut type_ = device::DeviceType::new().name(name.as_char_ptr()); - // TODO: ugly - type_.set_devnode::(); - inside.type_ = type_; - inside.kuid = Some(KuidT::global_root_uid()); - inside.kgid = Some(KgidT::global_root_gid()); - // here we cannot get the number from the nrdev, because this requires const - match name.to_str() { - Ok("clock") => { - let ele_chrdev_reg: Pin< - Box>, - > = chrdev::Registration::new_pinned(name, 0, this_module)?; - inside.register = Some(ele_chrdev_reg); - // register monotonic clock - inside - .register - .as_mut() - .unwrap() - .as_mut() - .register::()?; - // register realtime clock - inside - .register - .as_mut() - .unwrap() - .as_mut() - .register::()?; - } - Ok("thread") => { - let ele_chrdev_reg: Pin< - Box>, - > = chrdev::Registration::new_pinned(name, 0, this_module)?; - inside.register = Some(ele_chrdev_reg); - inside - .register - .as_mut() - .unwrap() - .as_mut() - .register::()?; - } - Ok("xbuf") => { - let ele_chrdev_reg: Pin< - Box>, - > = chrdev::Registration::new_pinned(name, 0, this_module)?; - inside.register = Some(ele_chrdev_reg); - inside - .register - .as_mut() - .unwrap() - .as_mut() - .register::()?; - } - Ok("proxy") => { - let ele_chrdev_reg: Pin< - Box>, - > = chrdev::Registration::new_pinned(name, 0, this_module)?; - inside.register = Some(ele_chrdev_reg); - inside - .register - .as_mut() - .unwrap() - .as_mut() - .register::()?; - } - Ok("observable") => { - let ele_chrdev_reg: Pin< - Box>, - > = chrdev::Registration::new_pinned(name, 0, this_module)?; - inside.register = Some(ele_chrdev_reg); - inside - .register - .as_mut() - .unwrap() - .as_mut() - .register::()?; - } - Ok(_) => { - pr_info!("not yet implemented"); - } - Err(_e) => { - pr_info!("should not meet here"); - } - } - // no need to call register here - // ele_chrdev_reg.as_mut().register::()?; //alloc_chrdev + cdev_alloc + cdev_add - // inside.register = Some(ele_chrdev_reg); - // inside.register.as_mut().unwrap().as_mut().register::()?; - // create_element_class end - - // FIXME: this should be variable. But the `register` needs a const value. We just hack for now. If we need more - // factory, we need to change the code here. One way here is to use index to find the struct. - - // let factory_ops = fac.locked_data().into_inner(); - if let RrosFactoryType::CLONE = flag { - chrdev_reg.as_mut().register::()?; - } + let inside: &mut RrosFactoryInside = &mut fac_lock.inside; + let mut idevname = CStr::from_bytes_with_nul("clone\0".as_bytes())?; + if let RrosFactoryType::SINGLE = flag { + // RROS_FACTORY_SINGLE + idevname = name; + inside.class = Some(rros_class.clone()); + inside.minor_map = Some(0); + inside.sub_rdev = Some(class::DevT::new(0)); + match idevname.to_str() { + Ok("control") => { + chrdev_reg.as_mut().register::()?; + } + Ok("poll") => { + chrdev_reg.as_mut().register::()?; } - if let RrosFactoryType::SINGLE | RrosFactoryType::CLONE = flag { - let rdev = chrdev_reg.as_mut().last_registered_devt().unwrap(); - let dev = create_sys_device(rdev, inside, ptr::null_mut() as *mut u8, idevname); - inside.device = Some(dev); + Ok(_) => { + pr_alert!("not yet implemented"); } + Err(_e) => { + pr_err!("should not meet here"); + } + } + } else { + // create_element_class + inside.minor_map = + Some(bitmap_zalloc(nrdev.try_into().unwrap(), bindings::GFP_KERNEL) as u64); + if inside.minor_map == Some(0) { + return Err(kernel::Error::EINVAL); + } - let mut index = RrosIndex { - rbtree: unsafe { SpinLock::new(rbtree::RBTree::new()) }, - generator: RROS_NO_HANDLE, - }; - let pinned = unsafe { Pin::new_unchecked(&mut index.rbtree) }; - spinlock_init!(pinned, "value"); - inside.index = Some(index); - - let mut hashname: [types::HlistHead; NAME_HASH_TABLE_SIZE as usize] = - [types::HlistHead::new(); NAME_HASH_TABLE_SIZE as usize]; - types::hash_init(hashname[0].as_list_head(), NAME_HASH_TABLE_SIZE); - inside.name_hash = Some(hashname); - let mut hash_lock = unsafe { SpinLock::new(0) }; - let pinned = unsafe { Pin::new_unchecked(&mut hash_lock) }; - spinlock_init!(pinned, "device_name_hash_lock"); - inside.hash_lock = Some(hash_lock); - 0 + inside.class = Some(Arc::try_new(class::Class::new( + this_module, + name.as_char_ptr(), + )?)?); + let mut type_ = device::DeviceType::new().name(name.as_char_ptr()); + // TODO: ugly + type_.set_devnode::(); + inside.type_ = type_; + inside.kuid = Some(KuidT::global_root_uid()); + inside.kgid = Some(KgidT::global_root_gid()); + // here we cannot get the number from the nrdev, because this requires const + match name.to_str() { + Ok("clock") => { + let ele_chrdev_reg: Pin< + Box>, + > = chrdev::Registration::new_pinned(name, 0, this_module)?; + inside.register = Some(ele_chrdev_reg); + // register monotonic clock + inside + .register + .as_mut() + .unwrap() + .as_mut() + .register::()?; + // register realtime clock + inside + .register + .as_mut() + .unwrap() + .as_mut() + .register::()?; + } + Ok("thread") => { + let ele_chrdev_reg: Pin< + Box>, + > = chrdev::Registration::new_pinned(name, 0, this_module)?; + inside.register = Some(ele_chrdev_reg); + inside + .register + .as_mut() + .unwrap() + .as_mut() + .register::()?; + } + Ok("xbuf") => { + let ele_chrdev_reg: Pin>> = + chrdev::Registration::new_pinned(name, 0, this_module)?; + inside.register = Some(ele_chrdev_reg); + inside + .register + .as_mut() + .unwrap() + .as_mut() + .register::()?; + } + Ok("proxy") => { + let ele_chrdev_reg: Pin< + Box>, + > = chrdev::Registration::new_pinned(name, 0, this_module)?; + inside.register = Some(ele_chrdev_reg); + inside + .register + .as_mut() + .unwrap() + .as_mut() + .register::()?; + } + Ok("observable") => { + let ele_chrdev_reg: Pin< + Box>, + > = chrdev::Registration::new_pinned(name, 0, this_module)?; + inside.register = Some(ele_chrdev_reg); + inside + .register + .as_mut() + .unwrap() + .as_mut() + .register::()?; + } + Ok(_) => { + pr_info!("not yet implemented"); + } + Err(_e) => { + pr_info!("should not meet here"); + } } - None => 1, + // no need to call register here + // ele_chrdev_reg.as_mut().register::()?; //alloc_chrdev + cdev_alloc + cdev_add + // inside.register = Some(ele_chrdev_reg); + // inside.register.as_mut().unwrap().as_mut().register::()?; + // create_element_class end + + // FIXME: this should be variable. But the `register` needs a const value. We just hack for now. If we need more + // factory, we need to change the code here. One way here is to use index to find the struct. + + // let factory_ops = fac.locked_data().into_inner(); + if let RrosFactoryType::CLONE = flag { + chrdev_reg.as_mut().register::()?; + } + } + if let RrosFactoryType::SINGLE | RrosFactoryType::CLONE = flag { + let rdev = chrdev_reg.as_mut().last_registered_devt().unwrap(); + let dev = create_sys_device(rdev, inside, ptr::null_mut() as *mut u8, idevname); + inside.device = Some(dev); + } + + let mut index = RrosIndex { + rbtree: unsafe { SpinLock::new(rbtree::RBTree::new()) }, + generator: RROS_NO_HANDLE, }; + let pinned = unsafe { Pin::new_unchecked(&mut index.rbtree) }; + spinlock_init!(pinned, "value"); + inside.index = Some(index); + + let mut hashname: [types::HlistHead; NAME_HASH_TABLE_SIZE as usize] = + [types::HlistHead::new(); NAME_HASH_TABLE_SIZE as usize]; + types::hash_init(hashname[0].as_list_head(), NAME_HASH_TABLE_SIZE); + inside.name_hash = Some(hashname); + let mut hash_lock = unsafe { SpinLock::new(0) }; + let pinned = unsafe { Pin::new_unchecked(&mut hash_lock) }; + spinlock_init!(pinned, "device_name_hash_lock"); + inside.hash_lock = Some(hash_lock); unsafe { fac.unlock() }; - match res { - 1 => Err(kernel::Error::EINVAL), - _ => Ok(0), - } + Ok(0) } // TODO: adjust the order of use and funciton in the whole project @@ -962,33 +1063,15 @@ impl FileOpener for CloneOps { let b = KgidT::from_inode_ptr(shared as *const u8); (*thread::RROS_THREAD_FACTORY.locked_data().get()) .inside - .as_mut() - .unwrap() .kuid = Some(a); (*thread::RROS_THREAD_FACTORY.locked_data().get()) .inside - .as_mut() - .unwrap() .kgid = Some(b); } // bindings::stream_open(); pr_debug!("open clone success"); Ok(Box::try_new(data)?) } - // fn open( - // _this: &Self, - // _file: &File, - // _data: &mut T, - // _offset: u64, - // ) -> Result { - // pr_debug!("I'm the open ops from the clone ops."); - - // unsafe { - // (*thread::RROS_THREAD_FACTORY.get_locked_data().get()).inside.as_ref().unwrap().kuid = i - - // }; - // Ok(1) - // } } // FIXME: all the ops is made for the thread factory. We need to change this later. @@ -1098,39 +1181,61 @@ pub fn rros_early_init_factories( Ok(chrdev_reg) } -// struct inode; +#[allow(dead_code)] +pub fn rros_open_element(inode: *mut bindings::inode, filp: &File) -> Result { + let e = unsafe { + &mut *(kernel::container_of!(&(*inode).__bindgen_anon_4.i_cdev, RrosElement, cdev) + as *mut RrosElement) + }; + // FIXME: CONFUSED.... + // let rce = Rc::try_new(RefCell::new(*e))?; + let mut ret = Ok(0); + unsafe { + rust_helper_rcu_read_lock(); + } -// pub fn rros_open_element(inode: *const bindings::inode, filp: &mut File)-> Result { -// let e = kernel::container_of!(&(*inode).__bindgen_anon_4.i_cdev, RrosElement, cdev); -// let rce = unsafe { Rc::try_new(RefCell::new(*e))? }; -// // rcu_read_lock(); + let flags = e.ref_lock.irq_lock_noguard(); -// // raw_spin_lock_irqsave(&e->ref_lock, flags); + if e.zombie { + ret = Err(Error::ESTALE); + } else { + if e.refs == 0 { + pr_debug!("Warning: rros_open_element: e->refs == 0"); + } + e.refs += 1; + } + e.ref_lock.irq_unlock_noguard(flags); -// // if (e->zombie) { -// // ret = -ESTALE; -// // } else { -// // RROS_WARN_ON(CORE, e->refs == 0); -// // e->refs++; -// // } + unsafe { + rust_helper_rcu_read_unlock(); + } -// // raw_spin_unlock_irqrestore(&e->ref_lock, flags); + if ret.is_err() { + return ret; + } -// // rcu_read_unlock(); + // FIXME: CONFUSED... + // ret = bind_file_to_element(filp.get_ptr(), rce.clone()); + if ret.is_err() { + // TODO: imple rros_put_element + e.put_element(); + return ret; + } -// // if (ret) -// // return ret; + unsafe { + bindings::stream_open(inode, filp.get_ptr()); + } -// bind_file_to_element(filp, rce.clone()); -// // if (ret) { -// // rros_put_element(e); -// // return ret; -// // } + ret +} -// // stream_open(inode, filp); +#[allow(dead_code)] +pub fn rros_release_element(_inode: *mut bindings::inode, filp: &File) -> Result { + let e = unsafe { &mut *unbind_file_to_element(filp) }; + e.put_element(); -// Ok(0) -// } + Ok(0) +} // impl FileOpenAdapter for Registration { // type Arg = T; @@ -1506,8 +1611,6 @@ pub fn rros_index_factory_element(e: Rc>) { rros_index_element( (*e.borrow_mut().factory.locked_data().get()) .inside - .as_mut() - .unwrap() .index .as_mut() .unwrap(), @@ -1521,8 +1624,6 @@ pub fn rros_unindex_factory_element(e: Rc>) { unsafe { let map = (*e.borrow_mut().factory.locked_data().get()) .inside - .as_ref() - .unwrap() .index .as_ref() .unwrap(); @@ -1533,7 +1634,7 @@ pub fn rros_unindex_factory_element(e: Rc>) { } // Example of using the `rros_get_element_by_fundle` function -// let e = rros_get_element_by_fundle((*thread::RROS_THREAD_FACTORY.locked_data().get()).inside.as_mut().unwrap().index.as_mut().unwrap(), fundle); +// let e = rros_get_element_by_fundle((*thread::RROS_THREAD_FACTORY.locked_data().get()).inside.index.as_mut().unwrap(), fundle); // let element: *mut T; // T means the type of the element. // if e.is_some() { // let e = e.unwrap(); diff --git a/kernel/rros/monitor.rs b/kernel/rros/monitor.rs index 640c9988c27da..5222cef607a65 100644 --- a/kernel/rros/monitor.rs +++ b/kernel/rros/monitor.rs @@ -313,7 +313,7 @@ pub static mut RROS_MONITOR_FACTORY: SpinLock = unsafe { dispose: Some(monitor_factory_dispose), attrs: None, //sysfs::attribute_group::new(), flags: factory::RrosFactoryType::CLONE, - inside: Some(factory::RrosFactoryInside { + inside: factory::RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -326,12 +326,12 @@ pub static mut RROS_MONITOR_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; #[allow(dead_code)] -pub fn monitor_factory_dispose(_ele: factory::RrosElement) {} +pub fn monitor_factory_dispose(_ele: &mut factory::RrosElement) {} struct MonitorOps; diff --git a/kernel/rros/observable.rs b/kernel/rros/observable.rs index be88a35df6306..15c66759b907c 100644 --- a/kernel/rros/observable.rs +++ b/kernel/rros/observable.rs @@ -802,16 +802,8 @@ impl FileOpener for ObservableOps { let b = KgidT::from_inode_ptr(shared as *const u8); // let a = KuidT((*(shared as *const u8 as *const bindings::inode)).i_uid); // let b = KgidT((*(shared as *const u8 as *const bindings::inode)).i_gid); - (*RROS_OBSERVABLE_FACTORY.locked_data().get()) - .inside - .as_mut() - .unwrap() - .kuid = Some(a); - (*RROS_OBSERVABLE_FACTORY.locked_data().get()) - .inside - .as_mut() - .unwrap() - .kgid = Some(b); + (*RROS_OBSERVABLE_FACTORY.locked_data().get()).inside.kuid = Some(a); + (*RROS_OBSERVABLE_FACTORY.locked_data().get()).inside.kgid = Some(b); } // bindings::stream_open(); Ok(Box::try_new(data)?) @@ -949,7 +941,7 @@ pub fn observable_factory_build( unsafe { (*observable_ptr).element.clone() } } -pub fn observable_factory_dispose(_ele: RrosElement) { +pub fn observable_factory_dispose(_ele: &mut RrosElement) { pr_debug!("[observable] observable_factory_dispose"); } @@ -961,7 +953,7 @@ pub static mut RROS_OBSERVABLE_FACTORY: SpinLock = unsafe dispose: Some(observable_factory_dispose), attrs: None, flags: factory::RrosFactoryType::CLONE, - inside: Some(RrosFactoryInside { + inside: RrosFactoryInside { type_: device::DeviceType::new(), class: None, cdev: None, @@ -974,6 +966,6 @@ pub static mut RROS_OBSERVABLE_FACTORY: SpinLock = unsafe name_hash: None, hash_lock: None, register: None, - }), + }, }) }; diff --git a/kernel/rros/poll.rs b/kernel/rros/poll.rs index 4bdcdc0c748ac..ea29494583acd 100644 --- a/kernel/rros/poll.rs +++ b/kernel/rros/poll.rs @@ -1131,7 +1131,7 @@ pub static mut RROS_POLL_FACTORY: SpinLock = unsafe { dispose: None, attrs: None, flags: factory::RrosFactoryType::SINGLE, - inside: Some(factory::RrosFactoryInside { + inside: factory::RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -1144,6 +1144,6 @@ pub static mut RROS_POLL_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; diff --git a/kernel/rros/proxy.rs b/kernel/rros/proxy.rs index 9768115d185b8..5c8cab787f671 100644 --- a/kernel/rros/proxy.rs +++ b/kernel/rros/proxy.rs @@ -848,7 +848,7 @@ pub static mut RROS_PROXY_FACTORY: SpinLock = unsafe { dispose: Some(proxy_factory_dispose), attrs: None, //sysfs::attribute_group::new(), flags: crate::factory::RrosFactoryType::CLONE, - inside: Some(RrosFactoryInside { + inside: RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -861,7 +861,7 @@ pub static mut RROS_PROXY_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; pub struct ProxyOps; @@ -940,4 +940,4 @@ impl FileOperations for ProxyOps { } } -pub fn proxy_factory_dispose(_ele: RrosElement) {} +pub fn proxy_factory_dispose(_ele: &mut RrosElement) {} diff --git a/kernel/rros/thread.rs b/kernel/rros/thread.rs index ef2aaf69db87f..ccfb92bd744d7 100644 --- a/kernel/rros/thread.rs +++ b/kernel/rros/thread.rs @@ -168,7 +168,7 @@ pub static mut RROS_THREAD_FACTORY: SpinLock = unsafe { attrs: None, //sysfs::attribute_group::new(), // TODO: rename this flags to the bit level variable RROS_FACTORY_CLONE and RROS_FACTORY_SINGLE flags: factory::RrosFactoryType::CLONE, - inside: Some(factory::RrosFactoryInside { + inside: factory::RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -181,7 +181,7 @@ pub static mut RROS_THREAD_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; @@ -1386,7 +1386,7 @@ unsafe extern "C" fn rust_handle_inband_event( // handle_cleanup_event(data); // break; _ => { - pr_warn!("unknown inband event"); + pr_debug!("unknown inband event"); } } } diff --git a/kernel/rros/xbuf.rs b/kernel/rros/xbuf.rs index ddf1548009147..ac1af44791de6 100644 --- a/kernel/rros/xbuf.rs +++ b/kernel/rros/xbuf.rs @@ -1025,7 +1025,7 @@ pub static mut RROS_XBUF_FACTORY: SpinLock = unsafe { dispose: Some(xbuf_factory_dispose), attrs: None, //sysfs::attribute_group::new(), flags: RrosFactoryType::CLONE, - inside: Some(RrosFactoryInside { + inside: RrosFactoryInside { type_: DeviceType::new(), class: None, cdev: None, @@ -1038,8 +1038,8 @@ pub static mut RROS_XBUF_FACTORY: SpinLock = unsafe { name_hash: None, hash_lock: None, register: None, - }), + }, }) }; -pub fn xbuf_factory_dispose(_ele: RrosElement) {} +pub fn xbuf_factory_dispose(_ele: &mut RrosElement) {} diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index b3700f28e037a..659f0e6c50b3c 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -121,6 +121,14 @@ impl Device { } } } + + /// Unregister the device using bindings::device_unregister + pub fn unregister(&mut self) { + // SAFETY: When we call unregister, dev is always valid. + unsafe { + bindings::device_unregister(self.0); + } + } } /// Class dev_node call back wrapper diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 03b8f4e418250..ffc487cb676d3 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -313,14 +313,16 @@ impl HlistNode { pub fn new() -> Self { Self(bindings::hlist_node::default()) } - // pub fn hash_del(&mut self){ - // extern "C"{ - // fn rust_helper_hash_del(node: *mut bindings::hlist_node); - // } - // unsafe{ - // rust_helper_hash_del(&mut self.0 as *mut bindings::hlist_node); - // } - // } + + /// Wrapper function rust_helper_hash_del + pub fn hash_del(&mut self) { + extern "C" { + fn rust_helper_hash_del(node: *mut bindings::hlist_node); + } + unsafe { + rust_helper_hash_del(&mut self.0 as *mut bindings::hlist_node); + } + } } #[derive(Clone, Copy)]