Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
$B3d$j9~$_$N8eH>It!"%U%!%$%k%7%9%F%`(B
[go: Go Back, main page]

$B3d$j9~$_$N8eH>It!"%U%!%$%k%7%9%F%`(B

					2024$BG/(B02$B7n(B07$BF|(B
$B>pJs2J3XN`(B $B%*%Z%l!<%F%#%s%0%7%9%F%`(B II

                                       $BC^GHBg3X(B $B%7%9%F%`>pJs7O(B 
                                       $B?7>k(B $BLw(B
                                       <yas@cs.tsukuba.ac.jp>

$B$3$N%Z!<%8$O!" https://www.coins.tsukuba.ac.jp/~yas/coins/os2-2023/2024-02-07
$B$"$k$$$O!" https://www.coins.tsukuba.ac.jp/~yas/
https://www.cs.tsukuba.ac.jp/~yas/

$B"#O"Mm;v9`(B

$B;n83$K$D$$$F(B $BIaDL$O!"(BTasklet $B$+(B Work Queue $B$r;H$($P$h$$!#(B

$BCm0U(B1: Tasklet $B$O!"(Btask $B9=B$BN$H$O$^$C$?$/4X78$J$$!#L>A0$,$h$/$J$$!#(B

$BCm0U(B2: Softirq $B$H$$$&MQ8l$r!"3d$j9~$_=hM}$N8eH>It$H$$$&0UL#$G;H$&?M$b$$(B $B$k!#(B

$BCm0U(B3: $BEAE}E*$J(BUnix$B$G$O!"(Btop half $B$O!"%7%9%F%`!&%3!<%k$+$iGI@8$9$k>e0L(B $BAX$N=hM}!"(Bbottom half $B$O!"3d$j9~$_$+$iGI@8$9$k2<0LAX$N=hM}$N0UL#$G;H$o(B $B$l$k$3$H$,$"$k!#(BLinux $B$G$O!"(Btop half, bottom half $B$O!"3d$j9~$_=hM}$NA0(B $BH>ItJ,$H8eH>ItJ,$N0UL#$K;H$&!#(B

$B"#(BTasklet

Tasklet $B$G#1$D$N;E;v$O linux-6.6.9/include/linux/interrupt.h 642: struct tasklet_struct 643: { 644: struct tasklet_struct *next; 645: unsigned long state; 646: atomic_t count; 647: bool use_callback; 648: union { 649: void (*func)(unsigned long data); 650: void (*callback)(struct tasklet_struct *t); 651: }; 652: unsigned long data; 653: };

$BA4BN$H$7$F!"tasklet_vec$B!
$B?^(B? Tasklet$B$K$*$1$k;E;v$N%-%e!<(B

$B"!(BTasklet$B$N9=B$BN$N@k8@(B

$B@EE*$K(B struct tasklet_struct $B$r@k8@$9$k$K$O!" DECLARE_TASKLET(name, func) $BM-8z$J(B(count==0) $B$N(B struct tasklet_struct $B$r@k8@$9$k(B DECLARE_TASKLET_DISABLED(name, func) $BL58z$J(B(count==1) $B$N(B struct tasklet_struct $B$r@k8@$9$k(B $BB>$N9=B$BN$K(B struct tasklet_struct $B$rKd$a9~$`;~$d(B kmalloc()$BEy$GF0E*$K3NJ]$7$?>l9g$K$O!" void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); void tasklet_setup(struct tasklet_struct *t, void (*callback)(struct tasklet_struct *)) $B$=$NB>$K!"@8@.>CLGM-8zL58z$K4X$7$F
  • tasklet_disable(): $BL58z2=$9$k!J%-%e!<$K$"$k$,$"$k$, tasklet_disable_nosync(): $BL58z2=$7!" tasklet_enable(): $BM-8z$K$9$k(B
  • tasklet_kill(): $B$G%-%e!<$+$i:o=|$9$k(B

    $B"!(BTasklet$B$N%O%s%I%i(B

    tasklet_init() $BEy$N>l9g!"(BTasklet $B$N%O%s%I%i$O!" void tasklet_handler(unsigned long data) { ... } tasklet_setup() $BEy$N>l9g!"(BTasklet $B$N%O%s%I%i$O!"struct timer_list$B$G<($7$?Nc(B $B$d(B $B8e=R$9$k(B EXT4_I()$B$HF1MM$K!"(B container_of() $B$G30B&$N9=B$BN$r void tasklet_handler(struct tasklet_struct *t) { ... }

    $B"!(BTasklet$B$N Tasklet $B$N%O%s%I%i$r void tasklet_schedule(struct tasklet_struct *t) Tasklet t $B$rDL>o$NM%@hEY$G%9%1%8%e!<%k$9$k(B void tasklet_hi_schedule(struct tasklet_struct *t) Tasklet t $B$r9bM%@hEY$G%9%1%8%e!<%k$9$k(B $B$9$k$H!"$=$l$O!V$=$N$&$A$K!W(B1$BEY$@$1$B"!(BTasklet$B$NMxMQNc(B

    $BL5@~(BLAN$B$N%I%i%$%P$G$NMxMQNc!#(B
    linux-6.6.9/drivers/net/wireless/ath/ath11k/ce.h
     167:	struct ath11k_ce_pipe {
    ...
     177:	        struct tasklet_struct intr_tq;
    ...
     182:	};
    
    linux-6.6.9/drivers/net/wireless/ath/ath11k/pcic.c
     616:	int ath11k_pcic_config_irq(struct ath11k_base *ab)
     617:	{
     618:	        struct ath11k_ce_pipe *ce_pipe;
    ...
     645:	                ce_pipe = &ab->ce.ce_pipe[i];
     646:	
     647:	                irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
     648:	
     649:	                tasklet_setup(&ce_pipe->intr_tq, ath11k_pcic_ce_tasklet);
    ...
     650:	
     651:	                ret = request_irq(irq, ath11k_pcic_ce_interrupt_handler,
     652:	                                  irq_flags, irq_name[irq_idx], ce_pipe);
    ...
     670:	}
    
  • $B=i4|2=;~$K!"$3$N9=B$BN$r(B tasklet_setup() $B$G=i4|2=$7$F$$$k!#(B
    linux-6.6.9/drivers/net/wireless/ath/ath11k/pcic.c
     391:	static irqreturn_t ath11k_pcic_ce_interrupt_handler(int irq, void *arg)
     392:	{
     393:	        struct ath11k_ce_pipe *ce_pipe = arg;
     394:	        struct ath11k_base *ab = ce_pipe->ab;
     395:	        int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
     396:	
     397:	        if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
     398:	                return IRQ_HANDLED;
     399:	
     400:	        /* last interrupt received for this CE */
     401:	        ce_pipe->timestamp = jiffies;
     402:	
     403:	        disable_irq_nosync(ab->irq_num[irq_idx]);
     404:	
     405:	        tasklet_schedule(&ce_pipe->intr_tq);
     406:	
     407:	        return IRQ_HANDLED;
     408:	}
    
     381:	static void ath11k_pcic_ce_tasklet(struct tasklet_struct *t)
     382:	{
     383:	        struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
     384:	        int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
     385:	
     386:	        ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
     387:	
     388:	        enable_irq(ce_pipe->ab->irq_num[irq_idx]);
     389:	}
    
    linux-6.6.9/include/linux/interrupt.h
     669:	#define from_tasklet(var, callback_tasklet, tasklet_fieldname)  \
     670:	        container_of(callback_tasklet, typeof(*var), tasklet_fieldname)
    

    $B"#(BWork Queue

    $B3d$j9~$_$K4XO"$7$?=hM}$G!"l9g(B(Tasklet$B$d(BSoftirq $B$G$OIT2DG=$J(B $B>l9g(B)$B$K(BWork Queue$B;H$&!#(B

    $B"!(BWork Queue$B$N%o!<%+!&%9%l%C%I(B

    Work Queue $B$N%o!<%+!&%9%l%C%I$O!"%+!<%M%k!&%l%Y%k$N%9%l%C%I$G!"(B $B3d$j9~$_=hM}$N8eH>ItJ,$N=hM}$r9T$&$3$H$,$G$-$k!#(B ($B3d$j9~$_=hM}0J30$G;H$C$F$b$h$$!#(B)

    workqueue_struct$B!
    $B?^(B? Work Queue$B$K$*$1$k;E;v$N%-%e!<(B

    $B%-%e!<$K$D$J$,$l$k;E;v$O!"(BTasklet $B$N;E;v$H$[$H$s$IF1$8$G!"4X?t$X$N%]%$(B $B%s%?(B func $B$H(B data $B$+$i$J$k!#=hM}$N

    $BHFMQ$N(B Work Queue $B%G%U%)%k%H$N%o!<%+!&%9%l%C%I$O!"(Bkworker/n (n$B$O%W%m%;%C(B $B%5HV9f(B) $B$H$h$P$l!"%W%m%;%C%5$4$H$K:n$i$l$k!##1$D$N%9%l%C%I$G!"MM!9$JMW(B $B5a85$N;E;v$r$3$J$9!#2<$NNc$G$O!"(B1$B$D$N%W%m%;%C%5$K(B4$B8D$N%9%l%C%I$,(B $B:n$i$l$F$$$k!#$=$N$&$A(B2$B$D$O!"(Bnice $BCM$,(B -20 $B$G9bM%@hEY!#(B

    $ ps alx | grep worker | wc [$B
         23     301    2310
    $ ps alx | grep 'worker.*/0' [$B
    1     0      59       2   0 -20      0     0 -      I<   ?          0:00 [kworker/0:1H-kblockd]
    1     0     759       2   0 -20      0     0 -      I<   ?          0:00 [kworker/0:2H-kblockd]
    1     0  293655       2  20   0      0     0 -      I    ?          0:00 [kworker/0:1-cgroup_destroy]
    1     0  294240       2  20   0      0     0 -      I    ?          0:00 [kworker/0:2-mm_percpu_wq]
    0  1013  294551  292317  20   0   9220  1156 -      S+   pts/1      0:00 grep worker.*/0
    $ ps alx | grep 'worker.*/0' [$B
    1     0      59       2   0 -20      0     0 -      I<   ?          0:00 [kworker/0:1H-kblockd]
    1     0     759       2   0 -20      0     0 -      I<   ?          0:00 [kworker/0:2H-kblockd]
    1     0  293655       2  20   0      0     0 -      I    ?          0:00 [kworker/0:1-cgroup_destroy]
    1     0  294240       2  20   0      0     0 -      I    ?          0:00 [kworker/0:2-events]
    0  1013  294554  292317  20   0   9220  1208 -      S+   pts/1      0:00 grep worker.*/0
    $ ps alx | head -1 [$B
    F   UID     PID    PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
    $ []
    
    $BHFMQ$N(B Work Queue $B$N%o!<%+!&%9%l%C%I$NB>$K!"@lMQ$N%o!<%+!&%9%l%C%I$r:n(B $B$k$3$H$b$G$-$k!#(B

    $B"!(Bwork_struct$B9=B$BN(B

    $B%o!<%/!&%-%e!<$GMQ$$$k(B 1 $B$D$N;E;v$O!"9=B$BN(B struct work_struct $B$GI=8=$5(B $B$l$k!#(B
    linux-6.6.9/include/linux/workqueue.h
      21:	typedef void (*work_func_t)(struct work_struct *work);
      98:	struct work_struct {
      99:	        atomic_long_t data;
     100:	        struct list_head entry;
     101:	        work_func_t func;
    ...
     105:	};
    
    linux-6.6.9/include/linux/types.h
     190:	struct list_head {
     191:	        struct list_head *next, *prev;
     192:	};
    
    $B struct work_struct my_work; ... INIT_WORK(&my_work,my_work_handler);

    $B"!(BWork Queue $B%O%s%I%i(B

    Work Queue $B%O%s%I%i$O!" void my_work_handler(struct work_struct *work) { ... }

    $B"!(BWork $B$N $B%O%s%I%i$r8F$S=P$7$?$$;~$K$O!" schedule_work(&work); $B$3$N7k2L!"(BINIT_WORK() $B$G@_Dj$7$?%O%s%I%i$,%o!<%+!&%9%l%C%I$K$h$j!V$=$N(B $B$&$A!W$K8F$S=P$5$l$k!#(B

    schedule_work() $B$G$O!"B(:B$K/$78e$K schedule_delayed_work(&work, ticks); ticks $B$O!"$I$N$/$i$$4V$r$H$k$+!#C10L$O!"(B ticks (jiffies$B$NC10L(B)$B!#(B $BB?$/$N%7%9%F%`$G(B10$B%_%jIC(B-1$B%_%jIC$G!"@_Dj$K$h$C$F0[$J$k!#(B

    $B"!(Bflush_scheduled_work()

    schedule_work() $B$GMW5a$7$?;E;v$,40N;$7$?$3$H$rBT$C$F!"$B"!(Balloc_workqueue()

    $B@lMQ$N%o!<%+!&%9%l%C%I$r:n$j$?$$;~$K$O!"
  • alloc_workqueue(): $B%o!<%+!&%9%l%C%I$r:n$k!#(B
  • queue_work(), queue_delayed_work():: $B%-%e!<$K;E;v$r2C$($k!#(B

    $B"!(BWork Queue$B$NMxMQNc(B

    x86 CMOS RTC $B$G$N3d$j9~$_%O%s%I%i$NNc!#(B $B:F7G!#(B
    linux-6.6.9/arch/x86/include/asm/mc146818rtc.h
     101:	#define RTC_IRQ 8
    
    linux-6.6.9/drivers/rtc/rtc-cmos.c
      73:	struct cmos_rtc {
      74:	        struct rtc_device       *rtc;
      75:	        struct device           *dev;
      76:	        int                     irq;
    ....
      92:	};
    
     697:	static struct cmos_rtc  cmos_rtc;
    
     920:	static int INITSECTION
     921:	cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
     922:	{
    ...
    1020:	        cmos_rtc.rtc = devm_rtc_allocate_device(dev);
    ...
    1077:	                        rtc_cmos_int_handler = hpet_rtc_interrupt;
    ...
    1088:	                retval = request_irq(rtc_irq, rtc_cmos_int_handler,
    1089:	                                0, dev_name(&cmos_rtc.rtc->dev),
    1090:	                                cmos_rtc.rtc);
    ...
    1101:	        retval = devm_rtc_register_device(cmos_rtc.rtc);
    ...
    1141:	}
    
     699:	static irqreturn_t cmos_interrupt(int irq, void *p)
     700:	{
     701:	        u8              irqstat;
    ...
     713:	        irqstat = CMOS_READ(RTC_INTR_FLAGS);
    ...
     740:	        if (is_intr(irqstat)) {
     741:	                rtc_update_irq(p, 1, irqstat);
     742:	                return IRQ_HANDLED;
     743:	        } else
     744:	                return IRQ_NONE;
     745:	}
    
    $B0J2 linux-6.6.9/include/linux/rtc.h 87: struct rtc_device { ... 112: struct work_struct irqwork; ... 164: }; linux-6.6.9/drivers/rtc/class.c 203: static struct rtc_device *rtc_allocate_device(void) 204: { 205: struct rtc_device *rtc; 206: 207: rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); ... 233: INIT_WORK(&rtc->irqwork, rtc_timer_do_work); ... 246: return rtc; 247: } linux-6.6.9/drivers/rtc/interface.c 900: void rtc_timer_do_work(struct work_struct *work) 901: { ... 966: } 683: void rtc_update_irq(struct rtc_device *rtc, 684: unsigned long num, unsigned long events) 685: { ... 690: schedule_work(&rtc->irqwork); 691: }

    $B"#3d$j9~$_$N8eH>It$NA*Br(B

    $B"#%U%!%$%k%7%9%F%`(B

    $B"!5a$a$i$l$k5!G=(B

    $B%7%9%F%`!&%3!<%k(B $BMM!9$JJ*M}G^BN$H@\B3J}K!$NMxMQ(B $BMM!9$J%G%#%9%/>e$NI=8=(B($B%U%!%$%k%7%9%F%`(B) $BCm0U(B: $B!V%U%!%$%k%7%9%F%`!W$H$$$&8@MU$,!"MM!9$J0UL#$G;H$o$l$k(B

    $B"!(Bstat()$B%7%9%F%`!&%3!<%k$H(Bstat$B%3%^%s%I(B

    STAT(2)                    Linux Programmer's Manual                   STAT(2)
    ...
           int stat(const char *path, struct stat *buf);
    ...
              struct stat {
                  dev_t     st_dev;     /* ID of device containing file */
                  ino_t     st_ino;     /* inode number */
                  mode_t    st_mode;    /* protection */
                  nlink_t   st_nlink;   /* number of hard links */
                  uid_t     st_uid;     /* user ID of owner */
                  gid_t     st_gid;     /* group ID of owner */
                  dev_t     st_rdev;    /* device ID (if special file) */
                  off_t     st_size;    /* total size, in bytes */
                  blksize_t st_blksize; /* blocksize for filesystem I/O */
                  blkcnt_t  st_blocks;  /* number of blocks allocated */
                  time_t    st_atime;   /* time of last access */
                  time_t    st_mtime;   /* time of last modification */
                  time_t    st_ctime;   /* time of last status change */
              };
    
    stat $B%3%^%s%I$r;H$&$H(B stat $B%7%9%F%`!&%3!<%k$GJV$5$l$kCM$K6a$$$b$N$,I=<((B $B$5$l$k!#(B
    $ stat .bashrc [$B
      File: .bashrc
      Size: 181       	Blocks: 9          IO Block: 1048576 regular file
    Device: 38h/56d	Inode: 28759903    Links: 1
    Access: (0644/-rw-r--r--)  Uid: ( 1013/     yas)   Gid: ( 5510/    prof)
    Access: 2024-02-01 22:12:30.143693000 +0900
    Modify: 2023-05-16 14:42:05.705198901 +0900
    Change: 2023-05-16 14:42:05.705198901 +0900
     Birth: -
    $ []
    

    $B"#(BVFS$B$N%*%V%8%'%/%H(B

    VFS$B$N
  • struct file, struct file_operations: $B3+$$$?%U%!%$%k!#%7!<%/!&%]%$(B $B%s%?$OJL!#(B
  • struct dentry, struct dentry_operations: directory entry$B!#%U%!%$%k(B $B$NL>A0!#(B
  • struct inode, struct inode_operations: $B%U%!%$%k!#3+$$$F$$$J$$$b$N(B $B$b4^$`!#(B
  • struct super_block, struct super_operations: $B%9!<%Q!<%V%m%C%/!J%^(B $B%&%s%H$5$l$?%U%!%$%k%7%9%F%`!K(B $B%U%!%$%k%7%9%F%`8GM-$N=hM}$O!"(B_operations $B$N$B?^(B?$B!!(Bstruct file,struct dentry,struct inode,struct super_block
    $B?^(B? $B%9!<%Q!<%V%m%C%/!"(Binode$B!"(Bdentry$B!"(Bfile

    $B"!(Bstruct file

    struct file $B$O!"%W%m%;%9$,%U%!%$%k$r(B open() $B$7$?;~$K3d$jEv$F$i$l$k!#(B
        int fd1 = open("file1",O_RDONLY);
        int fd2 = open("file1",O_RDONLY);
    
    $B%U%!%$%kL>(B "file1" $B$GI=8=$5$l$k%U%!%$%k$N(B inode $B9=B$BN$O!"(B1 $B8D$G$b!"(B file $B9=B$BN$O!"(B2 $B8D3d$jEv$F$i$l$k!#(B

    $B%G%#%9%/>e$K$OBP1~$9$k%G!<%?9=B$$OB8:_$7$J$$!#(B

    linux-6.6.9/include/linux/fs.h
     992:	struct file {
    ...
    1004:	        fmode_t                 f_mode;
    1005:	        atomic_long_t           f_count;
    ...
    1007:	        loff_t                  f_pos;
    ...
    1012:	        struct path             f_path;
    1013:	        struct inode            *f_inode;       /* cached value */
    1014:	        const struct file_operations    *f_op;
    ...
    1021:	        void                    *private_data;
    ...
    1027:	        struct address_space    *f_mapping;
    ...
    1030:	} __randomize_layout
    1031:	  __attribute__((aligned(4)));  /* lest something weird decides that 2 is OK */
    
    linux-6.6.9/include/linux/path.h
       8:	struct path {
       9:	        struct vfsmount *mnt;
      10:	        struct dentry *dentry;
      11:	} __randomize_layout;
    
    • f_path.dentry: $BBP1~$9$k(B dentry $B%*%V%8%'%/%H$X$N%]%$%s%?!#(B
    • f_mode: open() $B%7%9%F%`!&%3!<%k$N%b!<%I$r>/$7JQ7A$7$?$b$N!#(B FMODE_READ, FMODE_WRITE $BEy!#(B
    • f_pos: $B%U%!%$%k$rFI$_=q$-$9$k0LCV!#%7!<%/%]%$%s%?!#(B
    • f_count: $B;2>H%+%&%s%?!#%U%!%$%k$r3+$/$HA}$($k!#(Bfork() $B$9$k$H(B $BA}$($k!#(B close() $B$9$k$H8:$k!#(B
    • f_mapping: $B%U%!%$%k$NFbMF$r%W%m%;%9$N%"%I%l%96u4V$K%^%C%W$9$k;~$K(B $B;H$&(B($B%Z!<%8%-%c%C%7%e(B)$B!#(B
    • private_data: $B%U%!%$%k%7%9%F%`$K8GM-$N%G!<%?$rJ]B8$9$k!#(B $B!J7Q>5!"0Q>y$N0l

      $B"!7Q>5!&0Q>y$N C$B8@8l$K$h$k%*%V%8%'%/%H;X8~$N7Q>5!&0Q>y$N$B?^(B?

      $B?^(B? $BJ}K!#1(B

      $B?^(B?

      $B?^(B? $BJ}K!#2(B

      $B?^(B?

      $B?^(B? $BJ}K!#3(B

      $B"!(Bstruct file_operations

      $B%G%P%$%9%I%i%$%P$N2s(B $B$G$bEP>l$7$F$$$k!#(B

      struct file$B$NA`:n$O!"$?$H$($P struct file *file; file->f_op->read(file, buf, count, pos); f_op $B$K$O!"

      $B:F7G(B

      linux-6.6.9/include/linux/fs.h
      1852:	struct file_operations {
      1853:	        struct module *owner;
      1854:	        loff_t (*llseek) (struct file *, loff_t, int);
      1855:	        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
      1856:	        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
      1857:	        ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
      1858:	        ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
      1859:	        int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *,
      1860:	                        unsigned int flags);
      1861:	        int (*iterate_shared) (struct file *, struct dir_context *);
      1862:	        __poll_t (*poll) (struct file *, struct poll_table_struct *);
      1863:	        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
      1864:	        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
      1865:	        int (*mmap) (struct file *, struct vm_area_struct *);
      1866:	        unsigned long mmap_supported_flags;
      1867:	        int (*open) (struct inode *, struct file *);
      1868:	        int (*flush) (struct file *, fl_owner_t id);
      1869:	        int (*release) (struct inode *, struct file *);
      1870:	        int (*fsync) (struct file *, loff_t, loff_t, int datasync);
      1871:	        int (*fasync) (int, struct file *, int);
      1872:	        int (*lock) (struct file *, int, struct file_lock *);
      1873:	        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
      1874:	        int (*check_flags)(int);
      1875:	        int (*flock) (struct file *, int, struct file_lock *);
      1876:	        ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
      1877:	        ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
      1878:	        void (*splice_eof)(struct file *file);
      1879:	        int (*setlease)(struct file *, int, struct file_lock **, void **);
      1880:	        long (*fallocate)(struct file *file, int mode, loff_t offset,
      1881:	                          loff_t len);
      1882:	        void (*show_fdinfo)(struct seq_file *m, struct file *f);
      1883:	#ifndef CONFIG_MMU
      1884:	        unsigned (*mmap_capabilities)(struct file *);
      1885:	#endif
      1886:	        ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
      1887:	                        loff_t, size_t, unsigned int);
      1888:	        loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
      1889:	                                   struct file *file_out, loff_t pos_out,
      1890:	                                   loff_t len, unsigned int remap_flags);
      1891:	        int (*fadvise)(struct file *, loff_t, loff_t, int);
      1892:	        int (*uring_cmd)(struct io_uring_cmd *ioucmd, unsigned int issue_flags);
      1893:	        int (*uring_cmd_iopoll)(struct io_uring_cmd *, struct io_comp_batch *,
      1894:	                                unsigned int poll_flags);
      1895:	} __randomize_layout;
      
      $B
    • $BB?$/$OF1L>$N%7%9%F%`!&%3!<%k$r

      $B"!(Bstruct dentry (directory entry)

      struct dentry $B$O!"%G%#%l%/%H%j$K4^$^$l$F$$$kL>A0$NMWAG(B($B!V(B/$B!W$r4^$^$J$$(B $BL>A0(B)$B$rI=$99=B$BN!#(B struct dentry $B$O!"%a%b%jCf$K$N$_B8:_$9$k!#%G%#%9%/Cf$KBP1~$9$k%G!<%?$O(B $B$J$$!#%G%#%l%/%H%j$GL>A0$r8!:w$7$?$j%U%!%$%k$r:n@.$9$k;~$K%a%b%jCf$K:n(B $B$i$l$k!#(B
      linux-6.6.9/include/linux/dcache.h
        82:	struct dentry {
      ...
        87:	        struct dentry *d_parent;        /* parent directory */
        88:	        struct qstr d_name;
        89:	        struct inode *d_inode;          /* Where the name belongs to - NULL is
        90:	                                         * negative */
        91:	        unsigned char d_iname[DNAME_INLINE_LEN];        /* small names */
      ...
        94:	        struct lockref d_lockref;       /* per-dentry lock and refcount */
        95:	        const struct dentry_operations *d_op;
        96:	        struct super_block *d_sb;       /* The root of the dentry tree */
      ...
        98:	        void *d_fsdata;                 /* fs-specific data */
      ...
       104:	        struct list_head d_child;       /* child of parent list */
       105:	        struct list_head d_subdirs;     /* our children */
      ...
       114:	} __randomize_layout;
      
       283:	static inline unsigned d_count(const struct dentry *dentry)
       284:	{
       285:	        return dentry->d_lockref.count;
       286:	}
      
        35:	 #define HASH_LEN_DECLARE u32 hash; u32 len
      
        49:	struct qstr {
        50:	        union {
        51:	                struct {
        52:	                        HASH_LEN_DECLARE;
        53:	                };
        54:	                u64 hash_len;
        55:	        };
        56:	        const unsigned char *name;
        57:	};
      
        71:	# define DNAME_INLINE_LEN 32 /* 192 bytes */
      
      • d_inode: $B$3$N(B dentry $B$KBP1~$7$F$$$k(B inode $B!#(BNULL $B$J$iBP1~$7$F$$$k(B $B$b$N$,$J$$(B($B%M%,%F%#%V%-%c%C%7%e(B)$B!#(B
      • d_name, d_iname[]: $BJ8;zNs$NL>A0$rJ];}$9$k!#(B $BC;$$$b$N(B(DNAME_INLINE_LEN-1$B0J2<(B)$B$O!"(Bdentry $B9=B$BNCf$N(B d_iname[] $B$KF~$l$k!#D9$$$b$N$O!"(B $BJL$N>l=j$K%a%b%j$r3NJ]$7$FJ]B8$9$k!#(B
      • d_lockref.count: $B;2>H%+%&%s%?!#(B
      • d_op: dentry $B$rA`:n$9$k$?$a$N d_sb: superblock $B$X$N%]%$%s%?(B
      • d_parent: $B$=$N(B dentry $B$r4^$s$G$$$k%G%#%l%/%H%j$N(B dentry $B!#$?$H$($P!"(B /home/yas $B$H$$$&%Q%9L>$G!"(Byas $B$N(B d_parent $B$O!"(Bhome $B$N(B dentry $B$r;X$9!#(B home $B$N(B dentry $B$O!"(B/ $B$N(B dentry $B$r;X$9!#(B
      • d_child: $B6&DL$N(B d_parent $B$K4^$^$l$F$$$k(B d_entry $B$r$D$J$0!#(B
      • d_subdirs: $B<+J,<+?H$N;R6!$N%G%#%l%/%H%j(B
      • d_fsdata: $B%U%!%$%k%7%9%F%`8GM-$N%G!<%?!#(B
      dentry $B$O!"(B $B%9%i%V%"%m%1!<%?(B (kmem_cache_create(),kmem_cache_alloc(),kmem_cache_free())$B$G4IM}$5$l$F(B $B$$$k!#(B

      $B"!(Bdentry$B$N>uBV(B

      • $B;HMQCf(B: count $B$,(B 1 $B0J>e!#M-8z$J(Binode$B$rJ];}!#(B
      • $B6u$-(B: count $B$,(B 0$B!#M-8z$J(Binode$B$rJ];}!#%-%c%C%7%e$H$7$F%a%b%jCf$KB8:_$9$k!#(B $BF1$8%U%!%$%k$r:F$S(B open() $B$7$?;~$K9bB.!#(B $B%a%b%j$,ITB-$7$F$-$?$i>C$5$l$k$3$H$,$"$k(B>
      • $B%M%,%F%#%V!&%-%c%C%7%e(B: count $B$,Ii!#M-8z$J(B inode $B$rJ];}$7$F$$$J$$!#(B $B%U%!%$%k$,:o=|$5$l$?$+!"B8:_$7$J$$%U%!%$%k$r(B open() $B$7$h$&$H$7$?;~$K$=(B $B$N$h$&$J(B dentry $B$,:n$i$l$k!#(B $BB8:_$7$J$$%U%!%$%k$r7+$jJV$7(B open() $B$7$?;~$K%G%#%9%/$K9T$+$J$/$F$b%(%i!<(B ENOENT $B$,JV$;$k(B($B%M%,%F%#%V!&%-%c%C%7%e(B)$B!#(B

      $B"!(Bstruct inode

      struct inode $B$O!"A4$F$N%U%!%$%k!&%7%9%F%`$G6&DL$NMWAG$rJ];}$9$k!"%a%b%j(B $BCf$N9=B$BN!#3F%U%!%$%k!&%7%9%F%`$O!"$3$l$K4^$^$l$k$h$&$J%G!<%?$r$=$l$>(B $B$lFH<+$NJ}K!$G%G%#%9%/$KJ]B8$9$k!#(B
      linux-6.6.9/include/linux/fs.h
       639:	struct inode {
       640:	        umode_t                 i_mode;
       641:	        unsigned short          i_opflags;
       642:	        kuid_t                  i_uid;
       643:	        kgid_t                  i_gid;
      ...
       651:	        const struct inode_operations   *i_op;
       652:	        struct super_block      *i_sb;
      ...
       660:	        unsigned long           i_ino;
      ...
       669:	                const unsigned int i_nlink;
      ...
       672:	        dev_t                   i_rdev;
       673:	        loff_t                  i_size;
       674:	        struct timespec64       i_atime;
       675:	        struct timespec64       i_mtime;
       676:	        struct timespec64       __i_ctime; /* use inode_*_ctime accessors! */
       677:	        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
       678:	        unsigned short          i_bytes;
       679:	        u8                      i_blkbits;
       680:	        u8                      i_write_hint;
       681:	        blkcnt_t                i_blocks;
      ...
       694:	        struct hlist_node       i_hash;
      ...
       708:	                struct hlist_head       i_dentry;
      ...
       713:	        atomic_t                i_count;
      ...
       748:	        void                    *i_private; /* fs or device private pointer */
       749:	} __randomize_layout;
      
      • i_ino: inode$BHV9f!#%U%!%$%k%7%9%F%`$G%f%K!<%/!#(B
      • i_uid, i_gid, i_nlink, i_uid, i_gid, i_rdev, i_blkbits, i_size, i_atime, i_mtime, i_ctime, i_blocks, i_bytes, i_mode: $BB0@-!#(Bstat() $B%7%9%F%`!&%3!<(B $B%k$GJV$5$l$k!#(Bls -l $B$GI=<($5$l$k!#(B
      • i_op: $B$=$N(Binode$B$K8GM-$N i_sb: $BB0$7$F$$$k%U%!%$%k%7%9%F%`$N(B superblock $B$X$N%]%$%s%?!#(B
      • i_state: inode$B$N>uBV(B(dirty $B$+$I$&$+!"%G%#%9%/$X$N(B $B=q$-9~$_$r9T$C$F$$$k$+$I$&$+!"Ey(B)$B$rI=$9!#(B
      • i_hash: $B%U%!%$%k$r3+$/$3$H$N9bB.$N$?$a$N%O%C%7%eI=$r:n$k$?$a$N%U%#!<(B $B%k%I!#!!(B
      • i_dentry: $B$=$N(Binode$B$r4^$s$G$$$k(B dentry $B9=B$BN$N%j%9%H!#(B
      • i_count: $B;2>H%+%&%s%?!#(B0 $B$,L$;HMQ$N0UL#!#(B

      $B"!(Bstruct inode_operations

      inode$B$NA`:n$O!"$?$H$($P struct inode *inode; ... inode->i_op->create(idmap, inode, name, mode, true); i_op $B$K$O!" 1904: struct inode_operations { 1905: struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); 1906: const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); 1907: int (*permission) (struct mnt_idmap *, struct inode *, int); 1908: struct posix_acl * (*get_inode_acl)(struct inode *, int, bool); 1909: 1910: int (*readlink) (struct dentry *, char __user *,int); 1911: 1912: int (*create) (struct mnt_idmap *, struct inode *,struct dentry *, 1913: umode_t, bool); 1914: int (*link) (struct dentry *,struct inode *,struct dentry *); 1915: int (*unlink) (struct inode *,struct dentry *); 1916: int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *, 1917: const char *); 1918: int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *, 1919: umode_t); 1920: int (*rmdir) (struct inode *,struct dentry *); 1921: int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *, 1922: umode_t,dev_t); 1923: int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *, 1924: struct inode *, struct dentry *, unsigned int); 1925: int (*setattr) (struct mnt_idmap *, struct dentry *, struct iattr *); 1926: int (*getattr) (struct mnt_idmap *, const struct path *, 1927: struct kstat *, u32, unsigned int); 1928: ssize_t (*listxattr) (struct dentry *, char *, size_t); 1929: int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, 1930: u64 len); 1931: int (*update_time)(struct inode *, int); 1932: int (*atomic_open)(struct inode *, struct dentry *, 1933: struct file *, unsigned open_flag, 1934: umode_t create_mode); 1935: int (*tmpfile) (struct mnt_idmap *, struct inode *, 1936: struct file *, umode_t); 1937: struct posix_acl *(*get_acl)(struct mnt_idmap *, struct dentry *, 1938: int); 1939: int (*set_acl)(struct mnt_idmap *, struct dentry *, 1940: struct posix_acl *, int); 1941: int (*fileattr_set)(struct mnt_idmap *idmap, 1942: struct dentry *dentry, struct fileattr *fa); 1943: int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa); 1944: struct offset_ctx *(*get_offset_ctx)(struct inode *inode); 1945: } ____cacheline_aligned;
      • $BB?$/$N$b$N$O!"F1L>$N%7%9%F%`!&%3!<%k$H4XO"$7$F$$$k!#(B
      • $B0z?t$K$h$/8=$l$k(B struct mnt_idmap * $B$NCf?H$O!"L>A06u4V$rI=$99=B$(B $BBN(B struct user_namespace * ($B$H;2>H%+%&%s%?(B)$B!#L>A06u4V$,JL$@$H!"%k!<%H(B $B%G%#%l%/%H%j$rJL$K;}$F$k!#(B
      • create(): open() $B%7%9%F%`!&%3!<%k$d(B creat() $B%7%9%F%`!&%3!<%k$G!"%U%!(B $B%$%k$r:n@.$9$k;~$K8F$P$l$k!#0z?t$O!"%G%#%l%/%H%j$N(B inode$B!"$=$N%G%#%l%/(B $B%H%j$NCf$NL>A0$r<($9(B dentry$B!"L>A02r7h$G;H$&%G!<%?!#(B
      • lookup(): $B%U%!%$%kL>$r0z?t$K$9$k%7%9%F%`!&%3!<%k$N get_link(): $B%7%s%\%j%C%/!&%j%s%/$r$?$I$kA`:n$GMQ$$$k!#(B
      • permission(), get_acl(), set_acl(): $B%"%/%;%98"$N%A%'%C%/$GMQ$$$k!#(B
      • kstat, iattr, fileattr $B$OB0@-!#(B

      $B"!(Bstruct super_block

      $B%9!<%Q!<%V%m%C%/$O!"%U%!%$%k%7%9%F%`$N5/E@$H$J$k%G!<%?9=B$!#$=$N%U%!%$(B $B%k!&%7%9%F%`$K4^$^$l$F$$$k(B inode $B$d(B dentry $B$r4IM}$9$k!#(B
      linux-6.6.9/include/linux/fs.h
      1188:	struct super_block {
      ...
      1193:	        loff_t                  s_maxbytes;     /* Max file size */
      ...
      1195:	        const struct super_operations   *s_op;
      ...
      1237:	        void                    *s_fs_info;     /* Filesystem private info */
      ...
      1301:	        struct list_lru         s_dentry_lru;
      1302:	        struct list_lru         s_inode_lru;
      ...
      1315:	        struct list_head        s_inodes;       /* all inodes */
      ...
      1319:	} __randomize_layout;
      
      • s_maxbytes: $B:n@.$G$-$k%U%!%$%k$NBg$-$5$N:GBg!#(B
      • s_op: $B%U%!%$%k%7%9%F%`8GM-$N s_fs_info: $B%U%!%$%k%7%9%F%`$N%$%s%9%?%s%9!J%^%&%s%H$4$H$K0[$J$k!K(B $B$K8GM-$N%G!<%?!#%$%s%9%?%s%9JQ?t!#(B
      • s_root: $B$I$3$K%^%&%s%H$7$F$$$k$+$r$7$a$9%G%#%l%/%H%j(B
      • s_inodes, s_dentry_lru, s_inode_lru: $B%U%!%$%k%7%9%F%`$K4^$^$l$F$$(B $B$k(Binode $B$d(B dentry $B$r4IM}$9$k$?$a$N%U%#!<%k%I!#(B

      $B"!(Bstruct super_operations

      $B%9!<%Q!<%V%m%C%/$NA`:n$O!"$?$H$($P struct super_block *sh; ... sh->s_op->write_super(sb);
      linux-6.6.9/include/linux/fs.h
      1995:	struct super_operations {
      1996:	        struct inode *(*alloc_inode)(struct super_block *sb);
      1997:	        void (*destroy_inode)(struct inode *);
      1998:	        void (*free_inode)(struct inode *);
      1999:	
      2000:	        void (*dirty_inode) (struct inode *, int flags);
      2001:	        int (*write_inode) (struct inode *, struct writeback_control *wbc);
      2002:	        int (*drop_inode) (struct inode *);
      2003:	        void (*evict_inode) (struct inode *);
      2004:	        void (*put_super) (struct super_block *);
      2005:	        int (*sync_fs)(struct super_block *sb, int wait);
      2006:	        int (*freeze_super) (struct super_block *, enum freeze_holder who);
      2007:	        int (*freeze_fs) (struct super_block *);
      2008:	        int (*thaw_super) (struct super_block *, enum freeze_holder who);
      2009:	        int (*unfreeze_fs) (struct super_block *);
      2010:	        int (*statfs) (struct dentry *, struct kstatfs *);
      2011:	        int (*remount_fs) (struct super_block *, int *, char *);
      2012:	        void (*umount_begin) (struct super_block *);
      2013:	
      2014:	        int (*show_options)(struct seq_file *, struct dentry *);
      2015:	        int (*show_devname)(struct seq_file *, struct dentry *);
      2016:	        int (*show_path)(struct seq_file *, struct dentry *);
      2017:	        int (*show_stats)(struct seq_file *, struct dentry *);
      2018:	#ifdef CONFIG_QUOTA
      2019:	        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
      2020:	        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
      2021:	        struct dquot **(*get_dquots)(struct inode *);
      2022:	#endif
      2023:	        long (*nr_cached_objects)(struct super_block *,
      2024:	                                  struct shrink_control *);
      2025:	        long (*free_cached_objects)(struct super_block *,
      2026:	                                    struct shrink_control *);
      2027:	        void (*shutdown)(struct super_block *sb);
      2028:	};
      
      • alloc_inode: $B$=$N%U%!%$%k%7%9%F%`Fb$K(B inode $B9=B$BN$r3NJ]$9$k!#(B
      • destroy_inode: $B%a%b%jCf$N(B inode $B9=B$BN$r(B free $B$9$k!#(B
      • dirty_inode: inode $B$,(B dirty $B$G$"$k(B($B%G!<%?$NJQ99$r9T$C$?(B)$B$3$H$rEA$($k!#(B
      • write_inode: inode $B$r%G%#%9%/$X=q$/!#(B
      • put_super: $B%^%&%s%H$r2r=|(B($B%"%s%^%&%s%H(B)$B$N;~$K!"$=$N9=B$BN$,;2>H$5(B $B$l$J$/$J$C$?$3$H$rDLCN$9$k!#(B
      • sync_fs: $B99?7$5$l$?%9!<%Q!<%V%m%C%/$r%G%#%9%/$X=q$-=P$9!#(B
      • freeze_fs, unfreeze_fs: $B%U%!%$%k%7%9%F%`$NJQ99$r0l;~E*$K6X;_$9$k!?(B $B6X;_$r2r=|$9$k!#(BLVM (Logical Volume Manager) $B$G;H$&!#(B
      • statfs: $BE}7W>pJs(B($B6u$-MFNL!"(Binode$B?tEy(B)$B$rJV$9!#(B
      • remount_fs: $B%^%&%s%H$7$J$*$9!J%*%W%7%g%s$rJQ99$9$k!#Nc(B: ro (read-only)$B$+$i(Brw (read-write) $B$X!#!K(B

      $B"!(Btask_struct $B$H(B struct file

      struct file $B$O!"(Bstruct task_struct $B$+$i;X$5$l$k!#%U%!%$%k5-=R;R(Bfd$B$O!"(Bstruct task_struct *p; $B$N;~!"(Bp->files->fdt->fd[fd] $B$N(B struct file $B$rI=(B $B$9!#3+$$$F$$$k%U%!%$%k$N?t$,>.$5$$;~$O!"(B p->files->fd_array[fd]$B$HF1$8!#(B $BB?$/$N%U%!%$%k$r3+$/%W%m%;%9$G$O!"(B p->files->fd_array[NR_OPEN_DEFAULT]$B$GB-$j$J$/$J$C$?;~$O!"(B expand_files(), expand_fdtable() $B$G3HD%$9$k!#(B $B$3$l$i$N4X?t$G$O!"(Bkmalloc() $BEy$G%a%b%j$r3d$jEv$F$k!#(B
      linux-6.6.9/include/linux/sched.h
       743:	struct task_struct {
      ...
      1094:	        struct files_struct             *files;
      ...
      1554:	};
      
      linux-6.6.9/include/linux/fdtable.h
        24:	#define NR_OPEN_DEFAULT BITS_PER_LONG
      
        49:	struct files_struct {
      ...
        57:	        struct fdtable __rcu *fdt;
        58:	        struct fdtable fdtab;
      ...
        67:	        struct file __rcu * fd_array[NR_OPEN_DEFAULT];
        68:	};
      
        27:	struct fdtable {
      ...
        29:	        struct file __rcu **fd;      /* current fd array */
      ...
        34:	};
      
      linux-6.6.9/include/asm-generic/bitsperlong.h
         8:	#ifdef CONFIG_64BIT
         9:	#define BITS_PER_LONG 64
        10:	#else
        11:	#define BITS_PER_LONG 32
        12:	#endif /* CONFIG_64BIT */
      

      $B?^(B?$B!!(Bp-files->fd_array[fd]">
      $B?^(B? task_struct$B!"%U%!%$%k5-=R;R!"(Bfile$B9=B$BN!"$=$NB>(B

      $B"#(Bread() $B%7%9%F%`%3!<%k$H(B Ext4 $B%U%!%$%k%7%9%F%`(B

      read() $B%7%9%F%`!&%3!<%k$N$B"!(Bread() $B%7%9%F%`!&%3!<%k(B
    • linux-6.6.9/fs/read_write.c
       621:	SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
       622:	{
       623:	        return ksys_read(fd, buf, count);
       624:	}
      
       602:	ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
       603:	{
       604:	        struct fd f = fdget_pos(fd);
       605:	        ssize_t ret = -EBADF;
       606:	
       607:	        if (f.file) {
       608:	                loff_t pos, *ppos = file_ppos(f.file);
       609:	                if (ppos) {
       610:	                        pos = *ppos;
       611:	                        ppos = &pos;
       612:	                }
       613:	                ret = vfs_read(f.file, buf, count, ppos);
       614:	                if (ret >= 0 && ppos)
       615:	                        f.file->f_pos = pos;
       616:	                fdput_pos(f);
       617:	        }
       618:	        return ret;
       619:	}
      
      linux-6.6.9/include/linux/file.h
        36:	struct fd {
        37:	        struct file *file;
        38:	        unsigned int flags;
        39:	};
      
      • fdget_pos() $B$G!"(Bfd (int$B7?(B) $B$+$i(B struct file * $B$r4^$`(B struct fd $B$XJQ49$9$k!#(B $BFbItE*$K$O!"(Bcurrent->files->fd_array[fd] $B$H$@$$$?$$F1$8!#(B $B$5$i$K!"(Bpos $B$rA`:n$9$k$?$a$N%m%C%/$b file_ppos() $B$G!"8=:_$NFI$_=q$-$9$k0LCV(B pos $B$X$N%]%$%s%?$rF@!"$5$i$K!"$=$N(B $BFbMF$r%m!<%+%kJQ?t$K(B pos $B$K%3%T!<$9$k!#(B
      • vfs_read() $B$H$$$&(B VFS $BAX$N struct file $B$NCf$K$"$k(B pos $B$r99?7$9$k!#(B
      • fdput_pos() $B$G!"(Bpos $B$rA`:n$9$k$?$a$N%m%C%/$r3+J|$7$F$$$k!#(B

      $B"!(Bvfs_read()

      linux-6.6.9/fs/read_write.c
       450:	ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
       451:	{
       452:	        ssize_t ret;
       453:	
       454:	        if (!(file->f_mode & FMODE_READ))
       455:	                return -EBADF;
       456:	        if (!(file->f_mode & FMODE_CAN_READ))
       457:	                return -EINVAL;
       458:	        if (unlikely(!access_ok(buf, count)))
       459:	                return -EFAULT;
       460:	
       461:	        ret = rw_verify_area(READ, file, pos, count);
       462:	        if (ret)
       463:	                return ret;
       464:	        if (count > MAX_RW_COUNT)
       465:	                count =  MAX_RW_COUNT;
       466:	
       467:	        if (file->f_op->read)
       468:	                ret = file->f_op->read(file, buf, count, pos);
       469:	        else if (file->f_op->read_iter)
       470:	                ret = new_sync_read(file, buf, count, pos);
       471:	        else
       472:	                ret = -EINVAL;
       473:	        if (ret > 0) {
       474:	                fsnotify_access(file);
       475:	                add_rchar(current, ret);
       476:	        }
       477:	        inc_syscr(current);
       478:	        return ret;
       479:	}
      
       379:	static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
       380:	{
       381:	        struct kiocb kiocb;
       382:	        struct iov_iter iter;
       383:	        ssize_t ret;
       384:	
       385:	        init_sync_kiocb(&kiocb, filp);
       386:	        kiocb.ki_pos = (ppos ? *ppos : 0);
       387:	        iov_iter_ubuf(&iter, ITER_DEST, buf, len);
       388:	
       389:	        ret = call_read_iter(filp, &kiocb, &iter);
       390:	        BUG_ON(ret == -EIOCBQUEUED);
       391:	        if (ppos)
       392:	                *ppos = kiocb.ki_pos;
       393:	        return ret;
       394:	}
      
      linux-6.6.9/include/linux/fs.h
      1947:	static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio,
      1948:	                                     struct iov_iter *iter)
      1949:	{
      1950:	        return file->f_op->read_iter(kio, iter);
      1951:	}
      
      vfs_read() $B$O!"
    • file->f_mode$B$rD4$Y!"(B $B%U%!%$%k$,FI$_=P$7$G(B open() $B$5$l$F$$$J$1$1$l$P(B()$B!"%(%i! access_ok() $B$G!"7k2L$rJ]B8$9$k%a%b%j(B(buf, count)$B$,=q$-9~$_$G$-$J$$(B $B$H%(%i! rw_verify_area() $B$G!"%U%!%$%k$N$=$N>l=j(B(pos$B$+$i(Bpos+count$B$^$G(B)$B$,B8(B $B:_$9$k$+$r3NG'$9$k!#(B
    • __vfs_read() $B$O!"(Bfile$B9=B$BN$NA`:n$G(B file->f_op->read $B$H$$$C$? __vfs_read() $B$O!"(Bfile$B9=B$BN$NA`:n$G(B file->f_op->read_iter $B$H$$$C$? new_sync_read() $B$O!"(Bcall_read_iter() $B$r8F$V!#$3$l$O!"(B file->f_op->read_iter() $B$r8F$V!#(B

    $B"!(BExt4 $B$N(B file_operations

    linux-6.6.9/fs/ext4/file.c
     931:	const struct file_operations ext4_file_operations = {
     932:	        .llseek         = ext4_llseek,
     933:	        .read_iter      = ext4_file_read_iter,
     934:	        .write_iter     = ext4_file_write_iter,
     935:	        .iopoll         = iocb_bio_iopoll,
     936:	        .unlocked_ioctl = ext4_ioctl,
     937:	#ifdef CONFIG_COMPAT
     938:	        .compat_ioctl   = ext4_compat_ioctl,
     939:	#endif
     940:	        .mmap           = ext4_file_mmap,
     941:	        .mmap_supported_flags = MAP_SYNC,
     942:	        .open           = ext4_file_open,
     943:	        .release        = ext4_release_file,
     944:	        .fsync          = ext4_sync_file,
     945:	        .get_unmapped_area = thp_get_unmapped_area,
     946:	        .splice_read    = ext4_file_splice_read,
     947:	        .splice_write   = iter_file_splice_write,
     948:	        .fallocate      = ext4_fallocate,
     949:	};
     950:	
     951:	const struct inode_operations ext4_file_inode_operations = {
     952:	        .setattr        = ext4_setattr,
     953:	        .getattr        = ext4_file_getattr,
    ...
     960:	};
    
    linux-6.6.9/fs/ext4/super.c
    1627:	static const struct super_operations ext4_sops = {
    1628:	        .alloc_inode    = ext4_alloc_inode,
    1629:	        .free_inode     = ext4_free_in_core_inode,
    ...
    1647:	};
    
    • file_operations $B9=B$BN$N4X?t$N$&$A!"(B14 $B8D$rDj5A$7$F$$$k!#(B
    • $B generic_ $B$+$i;O$^$k$b$N(B $B$O!"7Q>5!?0Q>y!#(Biocb_bio_iopoll(), iter_file_splice_write() $B$b!"B>$N%U%!%$%k%7%9%F%`$H6&DL!#(Bext4 $B8GM-$G$O(B $B$J$$!#(B
    • inode $B$NA`:n!"(Bext4_file_inode_operations $B$b$"$k!#(B
    • $B%9!<%Q!<%V%m%C%/$NA`:n!"(Bext4_sops $B$b$"$k!#(B
    • dentry $B$NA`:n$GFCJL$JA`:n$r9T$&$?$a$N(B struct dentry_operations $B$O!"(B ext4 $B$G$ODj5A$5$l$F$$$J$$!#!!(B

    $B"!(BExt4 $B$N(B inode

    Ext4 $B$G$O!"%a%b%jCf$N%G!<%?$r9=B$BN(B struct ext4_inode_info $B$GI=$9!#(B
    linux-6.6.9/fs/ext4/ext4.h
     992:	struct ext4_inode_info {
    ...
    1081:	        struct inode vfs_inode;
    ...
    1156:	};
    
    1749:	static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
    1750:	{
    1751:	        return container_of(inode, struct ext4_inode_info, vfs_inode);
    1752:	}
    
    • Ext4 $BFH<+$N9=B$BN(B struct ext4_inode_info $B$NFbIt$K$O!"(BLinux $BI8=`$N(B struct inode $B$,$"$k!#(B
    • $BI8=`$N(B struct inode $B$+$i(B Ext4 $BFH<+$N(B struct ext4_inode_info $B$r EXT4_I() $B$O!"(B container_of() $B%^%/%m$r;H$C$F$$$k!#(B
    • container_of() $B$O!"Ev3:%a%s%P$N%*%U%;%C%H$r0z$-;;$7$F!"30B&$N9=B$(B $BBN$NHVCO$r5a$a$F$$$k!#(B

    $B?^(B?$B!!(Bstruct ext4_inode_info$B!
    $B?^(B? Ext4 $B%U%!%$%k%7%9%F%`$G;H$&9=B$BN(B ext4_inode_info $B$G$N(B struct inode $B$NJ];}(B

    $B"!(BExt4$B$N(Bext4_file_read_iter()

    linux-6.6.9/fs/ext4/file.c
     130:	static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
     131:	{
    ...
     147:	        return generic_file_read_iter(iocb, to);
     148:	}
    
    • $B%U%!%$%k$NFI$_=P$7$O!"(Bfilp->f_op->read_iter() $B$G Ext4 $B$G$O!"(Bread_iter() $B$O!"(Bext4_file_operations $B$GDj5A$5$l$F$$$k$h$&$K!"(B ext4_file_read_iter()$B!#(B
    • $B$3$l$O!"(BExt4 $B8GM-$N=hM}$,>/$7$"$k$,!"BgItJ,$N=hM}$O(B $BHFMQ$N(B generic_file_read_iter() $B$r8F$s$G

      $B"!HFMQ$N(Bgeneric_file_read_iter()

      linux-6.6.9/mm/filemap.c
      2789:	ssize_t
      2790:	generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
      2791:	{
      ...
      2831:	        return filemap_read(iocb, iter, retval);
      2832:	}
      
      • generic_file_read_iter() $B$O!"IaDL!"(Bgeneric_file_buffered_read() $B$r8F$V!#(B
      • $B%U%!%$%k$NF~=PNO$H%a%b%j4IM}$,E}9g$5$l$F$$$k!#F~=PNO$N

        $B"!HFMQ$N(Bfilemap_read()

        linux-6.6.9/include/linux/mm_types.h
         293:	struct folio {
        ...
         323:	                struct page page;
        ...
         361:	};
        
        linux-6.6.9/include/linux/pagevec.h
          28:	struct folio_batch {
          29:	        unsigned char nr;
          30:	        bool percpu_pvec_drained;
          31:	        struct folio *folios[PAGEVEC_SIZE];
          32:	};
        
        linux-6.6.9/mm/filemap.c
        2617:	ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
        2618:	                ssize_t already_read)
        2619:	{
        2620:	        struct file *filp = iocb->ki_filp;
        2621:	        struct file_ra_state *ra = &filp->f_ra;
        2622:	        struct address_space *mapping = filp->f_mapping;
        2623:	        struct inode *inode = mapping->host;
        2624:	        struct folio_batch fbatch;
        2625:	        int i, error = 0;
        2626:	        bool writably_mapped;
        2627:	        loff_t isize, end_offset;
        ...
        2636:	        folio_batch_init(&fbatch);
        2637:	
        2638:	        do {
        ...
        2652:	                error = filemap_get_pages(iocb, iter->count, &fbatch, false);
        ...
        2683:	                for (i = 0; i < folio_batch_count(&fbatch); i++) {
        2684:	                        struct folio *folio = fbatch.folios[i];
        ...
        2703:	                        copied = copy_folio_to_iter(folio, offset, bytes, iter);
        2704:	
        2705:	                        already_read += copied;
        2706:	                        iocb->ki_pos += copied;
        2707:	                        last_pos = iocb->ki_pos;
        ...
        2713:	                }
        ...
        2717:	                folio_batch_init(&fbatch);
        2718:	        } while (iov_iter_count(iter) && iocb->ki_pos < isize && !error);
        ...
        2722:	        return already_read ? already_read : error;
        2723:	}
        
        linux-6.6.9/include/linux/uio.h
         182:	static inline size_t copy_folio_to_iter(struct folio *folio, size_t offset,
         183:	                size_t bytes, struct iov_iter *i)
         184:	{
         185:	        return copy_page_to_iter(&folio->page, offset, bytes, i);
         186:	}
        
        • filemap_read() $B$O!"(Bfilemap_get_pages() $B$r8F$S!"%Z!<%8C10L$G(B $B%U%!%$%k$N%V%m%C%/$rFI$`!#(B
        • filemap_get_pages() $B$O!"%U%!%$%k$N%V%m%C%/$rFI$_!"(B struct page *page $B$NG[Ns(B (folio_batch) $B$K7k2L$rJV$9!#(B struct page *page $B$O!"J*M}%Z!<%8$H(B 1 $BBP(B 1 $B$KBP1~$9$k9=B$BN!#(B 1$B7n(B13$BF|$N(B $BJ*M}%a%b%j$N4IM}(B $B$G=P$F$-$?!#(B $B$3$3$+$i%U%!%$%kF~=PNO$N%Z!<%8%s%0$,E}9gE*$K for $BJ8$NCf$G$O!"%Z!<%8C10L$G%U%!%$%k$NFbMF$r%3%T!<$7$F$$$k!#(B
        • copy_page_to_iter() $B$O!"(Bcopy_to_user() $B$HF1MM$K!"%+!<%M%k$G4IM}$7(B $B$F$$$kJ*M}%a%b%j(B(struct page *page)$B$+$i%f!<%66u4VFb$N%a%b%j(B(iter)$B$K%3%T!<(B $B$9$k!#(B
        • $B%3%T!<$G$-$?$i!"%U%!%$%kCf$NFI$_=q$-$9$k0LCV(B pos $B$d(B $BFI$_9~$s$@%P%$%H?t(B already_read $B$r99?7$9$k!#(B
        • already_read $B$O!":G8e(B read() $B%7%9%F%`!&%3!<%k$NJV$jCM$H$7$F$b;H$o$l$k!#(B

        $B"#(Bmkdir() $B%7%9%F%`%3!<%k(B

        mkdir() $B%7%9%F%`!&%3!<%k$N$B"!(Bmkdir() $B%7%9%F%`!&%3!<%k(B
        linux-6.6.9/fs/namei.c
        4162:	SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
        4163:	{
        4164:	        return do_mkdirat(AT_FDCWD, getname(pathname), mode);
        4165:	}
        
        4157:	SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
        4158:	{
        4159:	        return do_mkdirat(dfd, getname(pathname), mode);
        4160:	}
        4161:	
        
        4128:	int do_mkdirat(int dfd, struct filename *name, umode_t mode)
        4129:	{
        4130:	        struct dentry *dentry;
        4131:	        struct path path;
        4132:	        int error;
        4133:	        unsigned int lookup_flags = LOOKUP_DIRECTORY;
        4134:	
        4135:	retry:
        4136:	        dentry = filename_create(dfd, name, &path, lookup_flags);
        ...
        4144:	                error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
        4145:	                                  dentry, mode);
        ...
        4153:	        putname(name);
        4154:	        return error;
        4155:	}
        
        • namei $B$O!"(Bname to inode $B$G!"L>A0$+$i(B inode $B$r mkdir() $B%7%9%F%`!&%3!<%k$N getname() $B$O!"%f!<%66u4V$K$"$k%U%!%$%kL>$r(B $B%+!<%M%k6u4V$K%3%T!<$7!"9=B$BN(B struct filename $B$KG<$a$k!#(B
        • do_mkdirat() $B$O!"(Bfilename_create() $B$G?7$7$/:n@.$9$k%G%#%l%/%H%j$N(B dentry $B$r:n$k!#(B $B$3$N;~E@$G$O!"%U%!%$%kL>$@$1$,@_Dj$5$l$?>uBV$K$J$C$F$*$j!"(Binode $B$O3dEv$F$i$l$F$$$J$$!#(B
        • vfs_mkdir() $B$r8F$S=P$9!#(B $B0z?t$O!"L>A06u4V(B($B$r4^$`(Bstruct mnt_idmap *)$B!"(B $B?F%G%#%l%/%H%j$N(B inode$B!"?7$7$/:n$i$l$k%G%#%l%/%H%j$N(B dentry$B!"(B $B?7$7$/:n$i$l$k%G%#%l%/%H%j$N%Q!<%_%C%7%g%s(B(rwxrwxrwx)$B$rI=$9(B mode (unsigned short)$B!#(B

        $B"!(Bvfs_mkdir()

        linux-6.6.9/fs/namei.c
        4100:	int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
        4101:	              struct dentry *dentry, umode_t mode)
        4102:	{
        ...
        4110:	        if (!dir->i_op->mkdir)
        4111:	                return -EPERM;
        ...
        4121:	        error = dir->i_op->mkdir(idmap, dir, dentry, mode);
        ...
        4124:	        return error;
        4125:	}
        
        • dir->i_op->mkdir()$B!!$H$$$&4X?t$,B8:_$7$J$1$l$P%(%i! dir->i_op->mkdir()$B!!$H$$$&4X?t$r8F$V!#(B

        $B"#2A%"%s%1!<%H(B

        $B>pJs2J3XN`$G$O!"650i$N2~A1$N$?$a$K!"3X@8$N3'$5$s$K2A%"%s%1!<%H$r(B $B

        $B%"%s%1!<%H$O(BTwins$B$+$i2sEz$7$F$/$@$5$$!#(B

        $B$J$*!"3'$5$s$NI>2A$,@.@S$K1F6A$9$k$3$H$O0l@Z$"$j$^$;$s!#(B $B$^$?!"I>2A7k2L$r650i$N2~A10J30$NL\E*$KMxMQ$9$k$3$H$O$"$j$^$;$s$7!"(B $BI>2A7k2L$r8x3+$9$k>l9g$K$O8D?M$rFCDj$G$-$k$h$&$J>pJs$O4^$a$^$;$s!#(B

        2$B7n(B26$BF|$^$G$K2sEz$7$F2<$5$$!#(B

        $B"#2]Bj(B5 $B3d$j9~$_$N8eH>It!"%U%!%$%k%7%9%F%`(B

        $B!zLdBj(B(501) Work Queue$B$N=i4|2=(B

        Work Queue $B$r;H$C$F$G8F$S=P$7$?$$!#(B
        void f(int arg1, int arg2) {
           $B>JN,(B;
        }
        
        $B$3$l$r static struct /*$B6uMs(B(a)*/ wq1; void work_queue_handler(struct work_struct *work) { /* Work Queue $B%O%s%I%i(B */ int arg1, arg2; arg1 = $B>JN,(B; /* f() $B$N0z?t(B */ arg2 = $B>JN,(B; /* f() $B$N0z?t(B */ /*$B6uMs(B(b)*/ } $B=i4|2=(B { /*$B6uMs(B(c)*/(&wq1, /*$B6uMs(B(d)*/); }

        $B!zLdBj(B(502) Work Queue$B%O%s%I%i$N $BItJ,(B($B%O!<%I%&%'%"$N3d$j9~$_(B)$B$N0lIt$G$"$k!#(B $B3d$j9~$_=hM}$N8eH>$G!"(B$BLdBj(B(501) $B$GDj5A$7$?(B Work Queue $B$N%O%s%I%i$r8F$V$h$&$K!"6uMs$rKd$a$J$5$$!#(B
        irqreturn_t irq_handler(int irq, void *dev) {
            /*$B6uMs(B(e)*/(/*$B6uMs(B(f)*/);
            return IRQ_HANDLED;
        }
        

        $B!zLdBj(B(503) struct file$B$NLr3d(B

        Linux $B%+!<%M%k$NCf$G!"%U%!%$%k$rI=8=$9$k$?$a$N%*%V%8%'%/%H$H$7$F(Bstruct inode $B$H(B struct file$B!!$,$"$k!#(B1 $B$B!zLdBj(B(504) Ext4$B%U%!%$%k%7%9%F%`(B

        read() $B%7%9%F%`!&%3!<%k$N

        $B$3$N%Z!<%8$G@bL@$5$l$F$$$k4X?t$N$&$A!"e$2$J$5$$!#(B

        • VFS $BAX$N4X?t(B:
        • $B%U%!%$%k%7%9%F%`(B Ext4 $B$K8GM-$N4X?t(B:

        $B!zLdBj(B(505) symlink()$B%7%9%F%`%3!<%k(B

        $BA0$H$J$k%U%!%$%kL>!"(B oldname $B$O!"?7$?$K:n@.$9$k%7%s%\%j%C%/!&%j%s%/$NFbMF$H$J$kJ8;zNs(B $B$r4^$`!#(B

        2024/02/07 18:00$BD{@5:Q$_!#6uMs(B(i)$B$,(B2$B$D$"$C$?$N$G!"#1$D$r6uMs(B(j)$B$K$7$^$7$?!#(B

        int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
                        struct dentry *dentry, const char *oldname)
        {
                int error;
        ...
                if (!/*$B6uMs(B(g)*/->i_op->/*$B6uMs(B(h)*/)
                        return -EPERM;
        ...
                error = /*$B6uMs(B(g)*/->i_op->/*$B6uMs(B(h)*/(idmap, /*$B6uMs(B(i)*/, /*$B6uMs(B(j)*/, /*$B>JN,(B*/);
        ...
                return error;
        }
        
        
        $BD{@5A0$N8m$j$r4^$`9T!#(B
                error = /*$B6uMs(B(g)*/->i_op->/*$B6uMs(B(h)*/(idmap, /*$B6uMs(B(j)*/, /*$B6uMs(B(i)*/, /*$B>JN,(B*/);
        

        $B!zLdBj(B(506) $B4|Kv;n83(B

        $B4|Kv;n83$K$D$$$F!"
      • $BF|IU(B:
      • $BMKF|(B:
      • $B3+;O;~9o(B:
      • $B;}$A9~$a$k$b$N(B:

      Last updated: 2024/02/09 12:51:15
      Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>